<!DOCTYPE html>
<html lang="zh-CN">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=2">
  <meta name="theme-color" content="#222">
  <meta name="generator" content="Hexo 4.2.1">
  <link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon-next.png">
  <link rel="icon" type="image/png" sizes="32x32" href="/images/favicon-32x32-next.png">
  <link rel="icon" type="image/png" sizes="16x16" href="/images/favicon-16x16-next.png">
  <link rel="mask-icon" href="/images/safari-pinned-tab.svg" color="#222">
  <link rel="stylesheet" href="/css/main.css">
  <link rel="stylesheet" href="/lib/font-awesome/css/all.min.css">
  <link rel="stylesheet" href="/lib/pace/pace-theme-minimal.min.css">
  <script src="/lib/pace/pace.min.js"></script>
  <script id="hexo-configurations">
    var NexT = window.NexT ||
    {};
    var CONFIG = {
      "hostname": "cuiqingcai.com",
      "root": "/",
      "scheme": "Pisces",
      "version": "7.8.0",
      "exturl": false,
      "sidebar":
      {
        "position": "right",
        "width": 360,
        "display": "post",
        "padding": 18,
        "offset": 12,
        "onmobile": false,
        "widgets": [
          {
            "type": "image",
            "name": "阿布云",
            "enable": false,
            "url": "https://www.abuyun.com/http-proxy/introduce.html",
            "src": "https://qiniu.cuiqingcai.com/88au8.jpg",
            "width": "100%"
      },
          {
            "type": "image",
            "name": "天验",
            "enable": true,
            "url": "https://tutorial.lengyue.video/?coupon=12ef4b1a-a3db-11ea-bb37-0242ac130002_cqx_850",
            "src": "https://qiniu.cuiqingcai.com/bco2a.png",
            "width": "100%"
      },
          {
            "type": "image",
            "name": "华为云",
            "enable": false,
            "url": "https://activity.huaweicloud.com/2020_618_promotion/index.html?bpName=5f9f98a29e2c40b780c1793086f29fe2&bindType=1&salesID=wangyubei",
            "src": "https://qiniu.cuiqingcai.com/y42ik.jpg",
            "width": "100%"
      },
          {
            "type": "image",
            "name": "张小鸡",
            "enable": false,
            "url": "http://www.zxiaoji.com/",
            "src": "https://qiniu.cuiqingcai.com/fm72f.png",
            "width": "100%"
      },
          {
            "type": "image",
            "name": "Luminati",
            "src": "https://qiniu.cuiqingcai.com/ikkq9.jpg",
            "url": "https://luminati-china.io/?affiliate=ref_5fbbaaa9647883f5c6f77095",
            "width": "100%",
            "enable": false
      },
          {
            "type": "image",
            "name": "IPIDEA",
            "url": "http://www.ipidea.net/?utm-source=cqc&utm-keyword=?cqc",
            "src": "https://qiniu.cuiqingcai.com/0ywun.png",
            "width": "100%",
            "enable": true
      },
          {
            "type": "tags",
            "name": "标签云",
            "enable": true
      },
          {
            "type": "categories",
            "name": "分类",
            "enable": true
      },
          {
            "type": "friends",
            "name": "友情链接",
            "enable": true
      },
          {
            "type": "hot",
            "name": "猜你喜欢",
            "enable": true
      }]
      },
      "copycode":
      {
        "enable": true,
        "show_result": true,
        "style": "mac"
      },
      "back2top":
      {
        "enable": true,
        "sidebar": false,
        "scrollpercent": true
      },
      "bookmark":
      {
        "enable": false,
        "color": "#222",
        "save": "auto"
      },
      "fancybox": false,
      "mediumzoom": false,
      "lazyload": false,
      "pangu": true,
      "comments":
      {
        "style": "tabs",
        "active": "gitalk",
        "storage": true,
        "lazyload": false,
        "nav": null,
        "activeClass": "gitalk"
      },
      "algolia":
      {
        "hits":
        {
          "per_page": 10
        },
        "labels":
        {
          "input_placeholder": "Search for Posts",
          "hits_empty": "We didn't find any results for the search: ${query}",
          "hits_stats": "${hits} results found in ${time} ms"
        }
      },
      "localsearch":
      {
        "enable": true,
        "trigger": "auto",
        "top_n_per_article": 10,
        "unescape": false,
        "preload": false
      },
      "motion":
      {
        "enable": false,
        "async": false,
        "transition":
        {
          "post_block": "bounceDownIn",
          "post_header": "slideDownIn",
          "post_body": "slideDownIn",
          "coll_header": "slideLeftIn",
          "sidebar": "slideUpIn"
        }
      },
      "path": "search.xml"
    };

  </script>
  <meta name="description" content="崔庆才的个人站点，记录生活的瞬间，分享学习的心得。">
  <meta property="og:type" content="website">
  <meta property="og:title" content="静觅">
  <meta property="og:url" content="https://cuiqingcai.com/page/6/index.html">
  <meta property="og:site_name" content="静觅">
  <meta property="og:description" content="崔庆才的个人站点，记录生活的瞬间，分享学习的心得。">
  <meta property="og:locale" content="zh_CN">
  <meta property="article:author" content="崔庆才">
  <meta property="article:tag" content="崔庆才">
  <meta property="article:tag" content="静觅">
  <meta property="article:tag" content="PHP">
  <meta property="article:tag" content="Java">
  <meta property="article:tag" content="Python">
  <meta property="article:tag" content="Spider">
  <meta property="article:tag" content="爬虫">
  <meta property="article:tag" content="Web">
  <meta property="article:tag" content="Kubernetes">
  <meta property="article:tag" content="深度学习">
  <meta property="article:tag" content="机器学习">
  <meta property="article:tag" content="数据分析">
  <meta property="article:tag" content="网络">
  <meta property="article:tag" content="IT">
  <meta property="article:tag" content="技术">
  <meta property="article:tag" content="博客">
  <meta name="twitter:card" content="summary">
  <link rel="canonical" href="https://cuiqingcai.com/page/6/">
  <script id="page-configurations">
    // https://hexo.io/docs/variables.html
    CONFIG.page = {
      sidebar: "",
      isHome: true,
      isPost: false,
      lang: 'zh-CN'
    };

  </script>
  <title>静觅丨崔庆才的个人站点</title>
  <meta name="google-site-verification" content="p_bIcnvirkFzG2dYKuNDivKD8-STet5W7D-01woA2fc" />
  <noscript>
    <style>
      .use-motion .brand,
      .use-motion .menu-item,
      .sidebar-inner,
      .use-motion .post-block,
      .use-motion .pagination,
      .use-motion .comments,
      .use-motion .post-header,
      .use-motion .post-body,
      .use-motion .collection-header
      {
        opacity: initial;
      }

      .use-motion .site-title,
      .use-motion .site-subtitle
      {
        opacity: initial;
        top: initial;
      }

      .use-motion .logo-line-before i
      {
        left: initial;
      }

      .use-motion .logo-line-after i
      {
        right: initial;
      }

    </style>
  </noscript>
  <link rel="alternate" href="/atom.xml" title="静觅" type="application/atom+xml">
</head>

<body itemscope itemtype="http://schema.org/WebPage">
  <div class="container">
    <div class="headband"></div>
    <header class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner">
        <div class="site-brand-container">
          <div class="site-nav-toggle">
            <div class="toggle" aria-label="切换导航栏">
              <span class="toggle-line toggle-line-first"></span>
              <span class="toggle-line toggle-line-middle"></span>
              <span class="toggle-line toggle-line-last"></span>
            </div>
          </div>
          <div class="site-meta">
            <a href="/" class="brand" rel="start">
              <span class="logo-line-before"><i></i></span>
              <h1 class="site-title">静觅 <span class="site-subtitle"> 崔庆才的个人站点 </span>
              </h1>
              <span class="logo-line-after"><i></i></span>
            </a>
          </div>
          <div class="site-nav-right">
            <div class="toggle popup-trigger">
              <i class="fa fa-search fa-fw fa-lg"></i>
            </div>
          </div>
        </div>
        <nav class="site-nav">
          <ul id="menu" class="main-menu menu">
            <li class="menu-item menu-item-home">
              <a href="/" rel="section">首页</a>
            </li>
            <li class="menu-item menu-item-archives">
              <a href="/archives/" rel="section">文章列表</a>
            </li>
            <li class="menu-item menu-item-tags">
              <a href="/tags/" rel="section">文章标签</a>
            </li>
            <li class="menu-item menu-item-categories">
              <a href="/categories/" rel="section">文章分类</a>
            </li>
            <li class="menu-item menu-item-about">
              <a href="/about/" rel="section">关于博主</a>
            </li>
            <li class="menu-item menu-item-message">
              <a href="/message/" rel="section">给我留言</a>
            </li>
            <li class="menu-item menu-item-search">
              <a role="button" class="popup-trigger">搜索 </a>
            </li>
          </ul>
        </nav>
        <div class="search-pop-overlay">
          <div class="popup search-popup">
            <div class="search-header">
              <span class="search-icon">
                <i class="fa fa-search"></i>
              </span>
              <div class="search-input-container">
                <input autocomplete="off" autocapitalize="off" placeholder="搜索..." spellcheck="false" type="search" class="search-input">
              </div>
              <span class="popup-btn-close">
                <i class="fa fa-times-circle"></i>
              </span>
            </div>
            <div id="search-result">
              <div id="no-result">
                <i class="fa fa-spinner fa-pulse fa-5x fa-fw"></i>
              </div>
            </div>
          </div>
        </div>
      </div>
    </header>
    <div class="back-to-top">
      <i class="fa fa-arrow-up"></i>
      <span>0%</span>
    </div>
    <div class="reading-progress-bar"></div>
    <main class="main">
      <div class="main-inner">
        <div class="content-wrap">
          <div class="content index posts-expand">
            <div class="carousel">
              <div id="wowslider-container">
                <div class="ws_images">
                  <ul>
                    <li><a target="_blank" href="https://cuiqingcai.com/5052.html"><img title="Python3网络爬虫开发实战教程" src="https://qiniu.cuiqingcai.com/ipy96.jpg" /></a></li>
                    <li><a target="_blank" href="https://t.lagou.com/fRCBRsRCSN6FA"><img title="52讲轻松搞定网络爬虫" src="https://qiniu.cuiqingcai.com/fqq5e.png" /></a></li>
                    <li><a target="_blank" href="https://brightdata.grsm.io/cuiqingcai"><img title="亮网络解锁器" src="https://qiniu.cuiqingcai.com/6qnb7.png" /></a></li>
                    <li><a target="_blank" href="https://cuiqingcai.com/4320.html"><img title="Python3网络爬虫开发视频教程" src="https://qiniu.cuiqingcai.com/bjrny.jpg" /></a></li>
                    <li><a target="_blank" href="https://cuiqingcai.com/5094.html"><img title="爬虫代理哪家强？十大付费代理详细对比评测出炉！" src="https://qiniu.cuiqingcai.com/nifs6.jpg" /></a></li>
                  </ul>
                </div>
                <div class="ws_thumbs">
                  <div>
                    <a target="_blank" href="#"><img src="https://qiniu.cuiqingcai.com/ipy96.jpg" /></a>
                    <a target="_blank" href="#"><img src="https://qiniu.cuiqingcai.com/fqq5e.png" /></a>
                    <a target="_blank" href="#"><img src="https://qiniu.cuiqingcai.com/6qnb7.png" /></a>
                    <a target="_blank" href="#"><img src="https://qiniu.cuiqingcai.com/bjrny.jpg" /></a>
                    <a target="_blank" href="#"><img src="https://qiniu.cuiqingcai.com/nifs6.jpg" /></a>
                  </div>
                </div>
                <div class="ws_shadow"></div>
              </div>
            </div>
            <link rel="stylesheet" href="/lib/wowslide/slide.css">
            <script src="/lib/wowslide/jquery.min.js"></script>
            <script src="/lib/wowslide/slider.js"></script>
            <script>
              jQuery("#wowslider-container").wowSlider(
              {
                effect: "cube",
                prev: "",
                next: "",
                duration: 20 * 100,
                delay: 20 * 100,
                width: 716,
                height: 297,
                autoPlay: true,
                playPause: true,
                stopOnHover: false,
                loop: false,
                bullets: 0,
                caption: true,
                captionEffect: "slide",
                controls: true,
                onBeforeStep: 0,
                images: 0
              });

            </script>
            <article itemscope itemtype="http://schema.org/Article" class="post-block index" lang="zh-CN">
              <link itemprop="mainEntityOfPage" href="https://cuiqingcai.com/30000.html">
              <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
                <meta itemprop="image" content="/images/avatar.png">
                <meta itemprop="name" content="崔庆才">
                <meta itemprop="description" content="崔庆才的个人站点，记录生活的瞬间，分享学习的心得。">
              </span>
              <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
                <meta itemprop="name" content="静觅">
              </span>
              <header class="post-header">
                <h2 class="post-title" itemprop="name headline">
                  <a class="label"> TypeScript <i class="label-arrow"></i>
                  </a>
                  <a href="/30000.html" class="post-title-link" itemprop="url">TypeScript教程一之基本类型</a>
                </h2>
              </header>
              <div class="post-body" itemprop="articleBody">
                <div class="thumb">
                  <img itemprop="contentUrl" class="random">
                </div>
                <div class="excerpt">
                  <p>
                  <p>之前的时候都是用 JavaScript 开发，但是最近发现随着项目的推进，一些项目越来越多地要求使用 TypeScript 来开发，所以不得不来专门学习一下 TypeScript 了，本篇文章就简单记录下学习 TypeScript 的过程。</p>
                  <h2 id="介绍"><a href="#介绍" class="headerlink" title="介绍"></a>介绍</h2>
                  <p>先看看 TypeScript 的官方介绍：</p>
                  <blockquote>
                    <p>Typed JavaScript at Any Scale. </p>
                    <p>TypeScript extends JavaScript by adding types. By understanding JavaScript, TypeScript saves you time catching errors and providing fixes before you run code. Any browser, any OS, anywhere JavaScript runs. Entirely Open Source.</p>
                  </blockquote>
                  <p>我们知道 JavaScript 是弱类型的语言，而实际上说白了就是加上类型标识的 JavaScript 语言，加上类型标识之后，可以帮助我们减少开发的调试成本，尽早发现错误，节省更多时间。同时 TypeScript 是完全开源的，它编译后得到的 JavaScript 支持任何浏览器和操作系统运行。</p>
                  <p>截止本文撰写的时间，TypeScript 已经更新到 4.1 版本，官方文档地址：<a href="https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-1.html。" target="_blank" rel="noopener">https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-1.html。</a></p>
                  <h2 id="相关资料"><a href="#相关资料" class="headerlink" title="相关资料"></a>相关资料</h2>
                  <p>学习 TypeScript 当然要看原汁原味的资料，推荐 TypeScript 官方的 Handbook，链接为：<a href="https://www.typescriptlang.org/docs/handbook/intro.html。" target="_blank" rel="noopener">https://www.typescriptlang.org/docs/handbook/intro.html。</a></p>
                  <p>本文所总结的内容基于 Handbook 的内容加上个人的一些修改而成。</p>
                  <p>另外本节的代码推荐大家直接在 TypeScript 提供的 Playgroud 里面运行即可，不用自己再初始化 Node 和 TypeScript 环境，简单方便，链接为：<a href="https://www.typescriptlang.org/play，大家直接打开就行了，预览如下：" target="_blank" rel="noopener">https://www.typescriptlang.org/play，大家直接打开就行了，预览如下：</a></p>
                  <p><img src="https://qiniu.cuiqingcai.com/eg15j.png" alt="image-20201228234110415"></p>
                  <p>比如默认情况下就有两行初始化代码：</p>
                  <figure class="highlight typescript">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="keyword">const</span> anExampleVariable = <span class="string">"Hello World"</span>;</span><br><span class="line"><span class="built_in">console</span>.log(anExampleVariable);</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>点击 Run 之后就可以直接运行，控制台输出结果显示在右侧，内容如下：</p>
                  <figure class="highlight markdown">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line">[<span class="symbol">LOG</span>]: <span class="link">"Hello World"</span></span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>如果你运行成功了，那我们就可以开始接下来的学习了。</p>
                  <p>下面正式开始介绍。</p>
                  <p>TypeScript 主要就是在 JavaScript 基础上扩展了一些类型，所以这里就分各种类型来进行介绍。</p>
                  <h2 id="基本类型"><a href="#基本类型" class="headerlink" title="基本类型"></a>基本类型</h2>
                  <h3 id="Boolean"><a href="#Boolean" class="headerlink" title="Boolean"></a>Boolean</h3>
                  <p>最常见的基本类型就是布尔类型了，其值就是 true 或者 false，类型声明用 boolean 就好了，在 TypeScript 中，声明一个 boolean 类型的变量写法如下：</p>
                  <figure class="highlight typescript">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="keyword">let</span> isDone: <span class="built_in">boolean</span> = <span class="literal">false</span>;</span><br><span class="line"><span class="built_in">console</span>.log(isDone, <span class="keyword">typeof</span> isDone);</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>这里注意到，声明类型可以在变量名的后面加上一个冒号，然后跟一个类型声明，和 Python 的 Type Hint 非常像。然后我们用 console 的 log 方法输出了这个变量，并用 typeof 输出了它的类型。</p>
                  <p>运行结果如下：</p>
                  <figure class="highlight autoit">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line">[<span class="built_in">LOG</span>]: <span class="literal">false</span>,  <span class="string">"boolean"</span></span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>可以看到运行结果就被输出出来了，同时 typeof 就是这个变量的类型，结果是一个字符串，就是 boolean。</p>
                  <p>是不是很简单？基本套路就是在变量的后面跟一个冒号再跟一个类型声明就好了。</p>
                  <h3 id="Number"><a href="#Number" class="headerlink" title="Number"></a>Number</h3>
                  <p>Number 即数值类型，对于这个类型，TypeScript 和 JavaScript 是一样的，Number 可以代表整数、浮点数、大整数。其中大整数需要单独用 bigint 来表示。另外 Number 还可以代表十六进制、八进制、二进制。</p>
                  <p>示例如下：</p>
                  <figure class="highlight typescript">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="keyword">let</span> decimal: <span class="built_in">number</span> = <span class="number">6</span>;</span><br><span class="line"><span class="keyword">let</span> hex: <span class="built_in">number</span> = <span class="number">0xf00d</span>;</span><br><span class="line"><span class="keyword">let</span> binary: <span class="built_in">number</span> = <span class="number">0b1010</span>;</span><br><span class="line"><span class="keyword">let</span> octal: <span class="built_in">number</span> = <span class="number">0o744</span>;</span><br><span class="line"><span class="keyword">let</span> big: bigint = <span class="number">100n</span>;</span><br><span class="line"></span><br><span class="line"><span class="built_in">console</span>.log(hex, <span class="keyword">typeof</span> hex);</span><br><span class="line"><span class="built_in">console</span>.log(big, <span class="keyword">typeof</span> big);</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>其中 bigint 需要 ES2020 的支持，需要在 TS Config 里面设置下：</p>
                  <p><img src="https://qiniu.cuiqingcai.com/qkhwz.png" alt="image-20201228235911831"></p>
                  <p>运行结果如下：</p>
                  <figure class="highlight markdown">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line">[<span class="symbol">LOG</span>]: <span class="link">61453,  "number" </span></span><br><span class="line">[<span class="symbol">LOG</span>]: <span class="link">100,  "bigint"</span></span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>这里输出了 hex 和 big 变量的值和类型，其中 hex 本身是用十六进制声明的，打印输出的时候被转化为了十进制，同时其类型为 number。</p>
                  <p>另外对于 bigint 类型来说，值的后面需要加一个 n，即 100 和 100n 代表的类型是不一样的，后者的类型是 bigint，前者的类型是 number。</p>
                  <p>假如把 bigint 类型的变量声明为 number 类型是会报错的，比如这样就是错误的：</p>
                  <figure class="highlight typescript">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="keyword">let</span> big: <span class="built_in">number</span> = <span class="number">100n</span>;</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>报错内容如下：</p>
                  <figure class="highlight routeros">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line">Type <span class="string">'bigint'</span> is <span class="keyword">not</span> assignable <span class="keyword">to</span><span class="built_in"> type </span><span class="string">'number'</span>.</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <h3 id="String"><a href="#String" class="headerlink" title="String"></a>String</h3>
                  <p>String 即字符串类型，需要用 string 来声明类型。字符串可以用单引号或者双引号或者斜引号声明，其中斜引号就是模板字符串。</p>
                  <p>示例如下：</p>
                  <figure class="highlight typescript">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="keyword">let</span> color: <span class="built_in">string</span> = <span class="string">"blue"</span>;</span><br><span class="line">color = <span class="string">'red'</span>;</span><br><span class="line"><span class="keyword">let</span> fullName: <span class="built_in">string</span> = <span class="string">`Bob Bobbington`</span>;</span><br><span class="line"><span class="keyword">let</span> age: <span class="built_in">number</span> = <span class="number">37</span>;</span><br><span class="line"><span class="keyword">let</span> sentence: <span class="built_in">string</span> = <span class="string">`Hello, my name is <span class="subst">$&#123;fullName&#125;</span>. I'll be <span class="subst">$&#123;age + <span class="number">1</span>&#125;</span> years old next month.`</span>;</span><br><span class="line"><span class="built_in">console</span>.log(sentence, <span class="keyword">typeof</span> sentence);</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>运行结果如下：</p>
                  <figure class="highlight 1c">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line">[<span class="built_in">LOG</span>]: <span class="string">"Hello, my name is Bob Bobbington. I'll be 38 years old next month."</span>,  <span class="string">"string"</span></span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>嗯，没什么特殊的，就是字符串类型。</p>
                  <h3 id="Array"><a href="#Array" class="headerlink" title="Array"></a>Array</h3>
                  <p>Array 即数组，声明可以有两种方式，一种是 <code>type[]</code> 这样的形式，一种是 Generics 泛型的形式，示例如下：</p>
                  <figure class="highlight typescript">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="keyword">let</span> list: <span class="built_in">number</span>[] = [<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>];</span><br><span class="line"><span class="keyword">let</span> list2: <span class="built_in">Array</span>&lt;<span class="built_in">number</span>&gt; = [<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>];</span><br><span class="line"><span class="keyword">let</span> list3: <span class="built_in">Array</span>&lt;<span class="built_in">any</span>&gt; = [<span class="number">1</span>, <span class="string">"2"</span>, <span class="number">3</span>];</span><br><span class="line"><span class="built_in">console</span>.log(list, <span class="keyword">typeof</span> list);</span><br><span class="line"><span class="built_in">console</span>.log(list2, <span class="keyword">typeof</span> list2);</span><br><span class="line"><span class="built_in">console</span>.log(list3, <span class="keyword">typeof</span> list3);</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>其中 list 就是使用了 <code>type[]</code> 这样的声明方式，声明为 <code>number[]</code>，那么数组里面的每个元素都必须要是 number 类型，list2 则是使用了泛型类型的声明，和 list 的效果是一样的，另外 list3 使用了 any 泛型类型，所以其值可以不仅仅为 number，因此这里 list3 的第二个元素设置为了字符串 2。</p>
                  <p>运行结果如下：</p>
                  <figure class="highlight prolog">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line">[<span class="symbol">LOG</span>]: [<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>],  <span class="string">"object"</span> </span><br><span class="line">[<span class="symbol">LOG</span>]: [<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>],  <span class="string">"object"</span> </span><br><span class="line">[<span class="symbol">LOG</span>]: [<span class="number">1</span>, <span class="string">"2"</span>, <span class="number">3</span>],  <span class="string">"object"</span></span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>结果的 typeof 输出的结果可能让人意外，不应该是输出其声明的类型吗，怎么是 object？这是因为浏览器真正执行的是刚才的 TypeScript 编译生成的 JavaScript，而 JavaScript 本身的 Array 和 Object 等类型，typeof 都统一返回 object 类型，因此得到的结果就是 object 了。</p>
                  <h3 id="Tuple"><a href="#Tuple" class="headerlink" title="Tuple"></a>Tuple</h3>
                  <p>Tuple 即元组，它可以允许我们声明固定数量和顺序的 Array，来看个例子就懂了：</p>
                  <figure class="highlight typescript">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="keyword">let</span> x: [<span class="built_in">string</span>, <span class="built_in">number</span>];</span><br><span class="line">x = [<span class="number">1</span>, <span class="number">2</span>]; <span class="comment">// Error</span></span><br><span class="line">x = [<span class="string">"Hello"</span>, <span class="number">2</span>]; <span class="comment">// Correct</span></span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>比如这里声明了一个变量 x，x 必须是一个 Array，按照顺序来说，其第一个元素必须要是 string，第二个元素必须要是 number，所以第二行的声明就会报错，第三行的声明才是正确的。</p>
                  <p>有了类型声明之后，在编译阶段就能发现错误或者编辑器给出方法输入提示。比如：</p>
                  <figure class="highlight typescript">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="built_in">console</span>.log(x[<span class="number">0</span>].substring(<span class="number">1</span>)); <span class="comment">// Correct</span></span><br><span class="line"><span class="built_in">console</span>.log(x[<span class="number">1</span>].substring(<span class="number">1</span>)); <span class="comment">// Error, Property 'substring' does not exist on type 'number'.</span></span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>比如这里第一行我们在敲 substring 的时候，编辑器根据类型判断出 <code>x[0]</code> 是 string 类型，那就可以给出 substring 的提示。而对于第二行代码的 <code>x[1]</code>，编译器会直接检查出其中存在错误，这有助于我们在静态类型检查时候及时发现问题，减少 Bug 出现的概率。</p>
                  <h3 id="Enum"><a href="#Enum" class="headerlink" title="Enum"></a>Enum</h3>
                  <p>Enum 即枚举类型，这个非常有用，有时候我们想定义的变量其实就只有某几种取值，那完全可以定义为枚举类型。</p>
                  <p>用法如下：</p>
                  <figure class="highlight typescript">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="keyword">enum</span> Stage &#123;</span><br><span class="line">    Debug,</span><br><span class="line">    Info,</span><br><span class="line">    Warning,</span><br><span class="line">    <span class="built_in">Error</span>,</span><br><span class="line">    Critical,</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> stage: Stage = Stage.Critical;</span><br><span class="line"><span class="built_in">console</span>.log(stage, <span class="keyword">typeof</span> stage);</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>这里我们声明了一个枚举类型，其名称叫做 Stage，值有五个。然后声明的变量直接用 Stage 修饰即可，值则可以直接取 Stage 的某个值，这里取值为 <code>Stage.Critical</code>。</p>
                  <p>最后打印输出该变量，结果如下：</p>
                  <figure class="highlight markdown">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line">[<span class="symbol">LOG</span>]: <span class="link">4,  "number"</span></span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>结果居然是 4，这个怎么情况？</p>
                  <p>原来是因为枚举类型，它会按照枚举值的声明顺序自动编号，比如 Debug 的值就是 0，Info 就是 1，以此类推。默认情况下是从 0 开始编号的，不过我们也可以手动更改编号的起始值，比如 Debug 从 1 开始编号，可以声明如下：</p>
                  <figure class="highlight typescript">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="keyword">enum</span> Stage &#123;</span><br><span class="line">    Debug = <span class="number">1</span>,</span><br><span class="line">    Info,</span><br><span class="line">    Warning,</span><br><span class="line">    <span class="built_in">Error</span>,</span><br><span class="line">    Critical,</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> stage: Stage = Stage.Critical;</span><br><span class="line"><span class="built_in">console</span>.log(stage, <span class="keyword">typeof</span> stage);</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>最后可以看到 Critical 的编号就变成 5 了，运行结果如下：</p>
                  <figure class="highlight markdown">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line">[<span class="symbol">LOG</span>]: <span class="link">5,  "number"</span></span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>有点意思。</p>
                  <p>那既然它是按照顺序来赋值的，那我如果在前面的值设置大一点，会不会出现后面的值和前面的值相等的情况？比如：</p>
                  <figure class="highlight typescript">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="keyword">enum</span> Stage &#123;</span><br><span class="line">    Debug = <span class="number">1</span>,</span><br><span class="line">    Info = <span class="number">3</span>,</span><br><span class="line">    Warning = <span class="number">2</span>,</span><br><span class="line">    <span class="built_in">Error</span>,</span><br><span class="line">    Critical,</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> stage: Stage = Stage.Error;</span><br><span class="line"><span class="keyword">let</span> stage2: Stage = Stage.Info;</span><br><span class="line"><span class="built_in">console</span>.log(stage, <span class="keyword">typeof</span> stage);</span><br><span class="line"><span class="built_in">console</span>.log(stage2, <span class="keyword">typeof</span> stage2);</span><br><span class="line"><span class="built_in">console</span>.log(stage == stage2);</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>看看这样会发生什么？这里 Error 按照常理来说会从 Warning 开始自增，值应该为 3，那 Info 我也设置为 3，二者会是相等吗？</p>
                  <p>运行结果如下：</p>
                  <figure class="highlight markdown">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line">[<span class="symbol">LOG</span>]: <span class="link">3,  "number" </span></span><br><span class="line">[<span class="symbol">LOG</span>]: <span class="link">3,  "number" </span></span><br><span class="line">[<span class="symbol">LOG</span>]: <span class="link">true</span></span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>果不其然，二者还都是 3，而且它们就是相等的。所以，对于枚举类型，我们一定要注意声明值的时候最好不要引起自增值和设定值之间的冲突，不然会引入不必要的麻烦。</p>
                  <p>另外对于枚举类型，我们还可以根据值进行查询，比如对于上述声明，我们不知道哪个值等于 2 或者 3，那可以直接将值传给 Stage 进行查询，得到的结果是一个字符串，示例如下：</p>
                  <figure class="highlight typescript">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="keyword">enum</span> Stage &#123;</span><br><span class="line">    Debug = <span class="number">1</span>,</span><br><span class="line">    Info = <span class="number">3</span>,</span><br><span class="line">    Warning = <span class="number">2</span>,</span><br><span class="line">    <span class="built_in">Error</span>,</span><br><span class="line">    Critical,</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> stage: <span class="built_in">string</span> = Stage[<span class="number">3</span>];</span><br><span class="line"><span class="built_in">console</span>.log(stage, <span class="keyword">typeof</span> stage);</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> stage2: <span class="built_in">string</span> = Stage[<span class="number">2</span>];</span><br><span class="line"><span class="built_in">console</span>.log(stage2, <span class="keyword">typeof</span> stage2);</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>运行结果如下：</p>
                  <figure class="highlight 1c">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line">[<span class="built_in">LOG</span>]: <span class="string">"Error"</span>,  <span class="string">"string"</span> </span><br><span class="line">[<span class="built_in">LOG</span>]: <span class="string">"Warning"</span>,  <span class="string">"string"</span></span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>比如这里 <code>Stage[2]</code> 就是查找枚举值等于 2 的枚举名称，结果是 Warning。那值相同的咋办呢？比如 3，看结果它返回的是 Error，看来 Error 把 Info 覆盖掉了，查询的结果是最新的一个枚举名称。注意这里返回的结果是字符串类型，不是枚举类型，它仅仅代表枚举的名称而已。</p>
                  <h3 id="Unknown"><a href="#Unknown" class="headerlink" title="Unknown"></a>Unknown</h3>
                  <p>Unknown 即未知类型，一般在类型不确定的情况下可以声明为 unknown 类型。比如说一个数据可能是 API 返回的，它可能是数值类型也可能是字符串类型，并不知道，这时候我们就可以将其声明为 unknown 类型。</p>
                  <p>示例如下：</p>
                  <figure class="highlight typescript">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="keyword">let</span> notSure: unknown = <span class="number">4</span>;</span><br><span class="line">notSure = <span class="string">"maybe a string instead"</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">// OK, definitely a boolean</span></span><br><span class="line">notSure = <span class="literal">false</span>;</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>比如这里 notSure 就声明了 unknown 类型，一开始它是数值类型，但当然也可以是字符串或者布尔类型。</p>
                  <p>那这样不就没啥用了吗？和 JavaScript 有啥不同吗？其实 unknown 还有其他用处，比如说编译器可以在一些判定条件下对 unknown 的值进行精确化处理，比如说一个 if 条件，判定了类型为布尔类型，那么其他和该类型相关的变量都会执行静态类型检查。示例如下：</p>
                  <figure class="highlight typescript">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="keyword">declare</span> <span class="keyword">const</span> maybe: unknown;</span><br><span class="line"><span class="comment">// 'maybe' could be a string, object, boolean, undefined, or other types</span></span><br><span class="line"><span class="keyword">const</span> aNumber: <span class="built_in">number</span> = maybe;</span><br><span class="line"><span class="comment">// Type 'unknown' is not assignable to type 'number'.</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> (maybe === <span class="literal">true</span>) &#123;</span><br><span class="line">  <span class="comment">// TypeScript knows that maybe is a boolean now</span></span><br><span class="line">  <span class="keyword">const</span> aBoolean: <span class="built_in">boolean</span> = maybe;</span><br><span class="line">  <span class="comment">// So, it cannot be a string</span></span><br><span class="line">  <span class="keyword">const</span> aString: <span class="built_in">string</span> = maybe;</span><br><span class="line">  <span class="comment">// Type 'boolean' is not assignable to type 'string'.</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> (<span class="keyword">typeof</span> maybe === <span class="string">"string"</span>) &#123;</span><br><span class="line">  <span class="comment">// TypeScript knows that maybe is a string</span></span><br><span class="line">  <span class="keyword">const</span> aString: <span class="built_in">string</span> = maybe;</span><br><span class="line">  <span class="comment">// So, it cannot be a boolean</span></span><br><span class="line">  <span class="keyword">const</span> aBoolean: <span class="built_in">boolean</span> = maybe;</span><br><span class="line">  <span class="comment">// Type 'string' is not assignable to type 'boolean'.</span></span><br><span class="line">&#125;</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>这里使用 declare 声明了一个类型变量，然后通过类型变量里面的判定条件就能配合检查其他变量的类型了。</p>
                  <h3 id="Any"><a href="#Any" class="headerlink" title="Any"></a>Any</h3>
                  <p>和 Unknown 的情形类似，我们还可以使用 any 来代表任意的类型，示例如下：</p>
                  <figure class="highlight typescript">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="keyword">declare</span> <span class="function"><span class="keyword">function</span> <span class="title">getValue</span>(<span class="params">key: <span class="built_in">string</span></span>): <span class="title">any</span></span>;</span><br><span class="line"><span class="comment">// OK, return value of 'getValue' is not checked</span></span><br><span class="line"><span class="keyword">const</span> str: <span class="built_in">string</span> = getValue(<span class="string">"myString"</span>);</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>这里声明了一个方法，返回类型就是 any，这样的话返回类型就可以是任意的结果了。</p>
                  <p>那 any 和 unknown 有什么不同呢？any 的自由度会更高一点，如果声明为 any，那么静态类型检查都会通过，即使某个变量的属性不存在。示例如下：</p>
                  <figure class="highlight typescript">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="keyword">let</span> looselyTyped: <span class="built_in">any</span> = <span class="number">4</span>;</span><br><span class="line"><span class="comment">// OK, ifItExists might exist at runtime</span></span><br><span class="line">looselyTyped.ifItExists();</span><br><span class="line"><span class="comment">// OK, toFixed exists (but the compiler doesn't check)</span></span><br><span class="line">looselyTyped.toFixed();</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> strictlyTyped: unknown = <span class="number">4</span>;</span><br><span class="line">strictlyTyped.toFixed();</span><br><span class="line"><span class="comment">// Error, Object is of type 'unknown'.</span></span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>可以看到，前两行的静态类型检查是能过的，但是 unknown 就过不了。</p>
                  <p>所以，什么时候用 unknown 什么时候用 any 呢？可以从含义上来进行区分：如果某个变量我确实就不知道它的类型，即我没办法知道它的类型，那就用 unknown；如果某个值但其实我确实有办法知道可能的类型，但确实它的类型自由度比较高，那就可以被声明为 any。</p>
                  <p>但在不必要的情况下，尽量减少 any 类型的使用。</p>
                  <h3 id="Void"><a href="#Void" class="headerlink" title="Void"></a>Void</h3>
                  <p>Void 一般用于声明方法的返回值，如果一个方法不返回任何结果，那就用 Void，示例如下：</p>
                  <figure class="highlight typescript">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">warnUser</span>(<span class="params"></span>): <span class="title">void</span> </span>&#123;</span><br><span class="line">  <span class="built_in">console</span>.log(<span class="string">"This is my warning message"</span>);</span><br><span class="line">&#125;</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <h3 id="Null-和-Undefined"><a href="#Null-和-Undefined" class="headerlink" title="Null 和 Undefined"></a>Null 和 Undefined</h3>
                  <p>其实 TypeScript 还专门为 null 和 undefined 声明了类型，一般 null 就声明为 null 类型，undefined 就声明为 undefined 类型，不过这两个并不太常用，示例如下：</p>
                  <figure class="highlight typescript">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="comment">// Not much else we can assign to these variables!</span></span><br><span class="line"><span class="keyword">let</span> u: <span class="literal">undefined</span> = <span class="literal">undefined</span>;</span><br><span class="line"><span class="keyword">let</span> n: <span class="literal">null</span> = <span class="literal">null</span>;</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>另外对于其他类型来说，其值也可以是 null 或者 undefined，比如 number 类型的变量，其值为 null 也是完全可以的。不过这里有个前提条件就是，TS Config 里面的 strictNullChecks 应该是关闭状态，不然会报错的。</p>
                  <p>设置如下：</p>
                  <p><img src="https://qiniu.cuiqingcai.com/ricrd.png" alt="image-20201229014015393"></p>
                  <p>比如：</p>
                  <figure class="highlight typescript">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="keyword">let</span> a: <span class="built_in">number</span> = <span class="literal">undefined</span>;</span><br><span class="line"><span class="keyword">let</span> b: <span class="built_in">string</span> = <span class="literal">null</span>;</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>这样就是没问题的了。</p>
                  <h3 id="Never"><a href="#Never" class="headerlink" title="Never"></a>Never</h3>
                  <p>这个类型也比较特殊，它代表你永远得不到它的结果。比如一个方法始终抛出一个异常，或者处于一个无限循环中，那么就可以声明为 never，示例如下：</p>
                  <figure class="highlight typescript">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="comment">// Function returning never must not have a reachable end point</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">error</span>(<span class="params">message: <span class="built_in">string</span></span>): <span class="title">never</span> </span>&#123;</span><br><span class="line">  <span class="keyword">throw</span> <span class="keyword">new</span> <span class="built_in">Error</span>(message);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// Inferred return type is never</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">fail</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="keyword">return</span> error(<span class="string">"Something failed"</span>);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// Function returning never must not have a reachable end point</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">infiniteLoop</span>(<span class="params"></span>): <span class="title">never</span> </span>&#123;</span><br><span class="line">  <span class="keyword">while</span> (<span class="literal">true</span>) &#123;&#125;</span><br><span class="line">&#125;</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <h3 id="Object"><a href="#Object" class="headerlink" title="Object"></a>Object</h3>
                  <p>Object 是 JavaScript 本身带有的类型，它表示非原始型的类型，即任何不是 number、string、boolean、bigint、symbol、null、undefined 的类型。</p>
                  <p>示例如下：</p>
                  <figure class="highlight typescript">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="keyword">declare</span> <span class="function"><span class="keyword">function</span> <span class="title">create</span>(<span class="params">o: object | <span class="literal">null</span></span>): <span class="title">void</span></span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">// OK</span></span><br><span class="line">create(&#123; prop: <span class="number">0</span> &#125;);</span><br><span class="line">create(<span class="literal">null</span>);</span><br><span class="line">create(<span class="number">42</span>);</span><br><span class="line"><span class="comment">// Error, Argument of type '42' is not assignable to parameter of type 'object | null'.</span></span><br><span class="line">create(<span class="string">"string"</span>);</span><br><span class="line"><span class="comment">// Error, Argument of type '"string"' is not assignable to parameter of type 'object | null'.</span></span><br><span class="line">create(<span class="literal">false</span>);</span><br><span class="line"><span class="comment">// Error, Argument of type 'false' is not assignable to parameter of type 'object | null'.</span></span><br><span class="line">create(<span class="literal">undefined</span>);</span><br><span class="line"><span class="comment">// Error, Argument of type 'undefined' is not assignable to parameter of type 'object | null'.</span></span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>不过，一般不用。</p>
                  <h3 id="Type-assertions"><a href="#Type-assertions" class="headerlink" title="Type assertions"></a>Type assertions</h3>
                  <p>一般情况下，我们确确实实知道某个变量属于什么类型，或者在某种情况下确实需要这种类型的转化，则可以显式的声明某个类型，示例如下：</p>
                  <figure class="highlight typescript">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="keyword">let</span> someValue: unknown = <span class="string">"this is a string"</span>;</span><br><span class="line"><span class="keyword">let</span> strLength: <span class="built_in">number</span> = (someValue <span class="keyword">as</span> <span class="built_in">string</span>).length;</span><br><span class="line"><span class="keyword">let</span> someValue2: unknown = <span class="string">"this is a string"</span>;</span><br><span class="line"><span class="keyword">let</span> strLength2: <span class="built_in">number</span> = (&lt;<span class="built_in">string</span>&gt;someValue2).length;</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>这里有两种使用方式，一种是 as，一种是尖括号声明。</p>
                  <h2 id="注意"><a href="#注意" class="headerlink" title="注意"></a>注意</h2>
                  <p>另外值得注意到是，以上的一些类型声明，使用大写形式 <code>Number</code>, <code>String</code>, <code>Boolean</code>, <code>Symbol</code> and <code>Object</code> 也是可以的，不过不推荐这么做，推荐还是用小写的形式。</p>
                  <p>比如这样其实是可以的：</p>
                  <figure class="highlight typescript">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">reverse</span>(<span class="params">s: <span class="built_in">String</span></span>): <span class="title">String</span> </span>&#123;</span><br><span class="line">  <span class="keyword">return</span> s.split(<span class="string">""</span>).reverse().join(<span class="string">""</span>);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">reverse(<span class="string">"hello world"</span>);</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>但更推荐使用小写，写成如下形式：</p>
                  <figure class="highlight typescript">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">reverse</span>(<span class="params">s: <span class="built_in">string</span></span>): <span class="title">string</span> </span>&#123;</span><br><span class="line">  <span class="keyword">return</span> s.split(<span class="string">""</span>).reverse().join(<span class="string">""</span>);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">reverse(<span class="string">"hello world"</span>);</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2>
                  <p>以上便是一些基本的类型声明方式，暂时先总结这么多，后面还会继续整理更高级的用法，比如 Function、Interface、Class 等。</p>
                  </p>
                </div>
              </div>
              <div class="post-meta">
                <span class="post-meta-item">
                  <span class="post-meta-item-icon">
                    <i class="far fa-user"></i>
                  </span>
                  <span class="post-meta-item-text">作者</span>
                  <span><a href="/authors/崔庆才" class="author" itemprop="url" rel="index">崔庆才</a></span>
                </span>
                <span class="post-meta-item">
                  <span class="post-meta-item-icon">
                    <i class="far fa-calendar"></i>
                  </span>
                  <span class="post-meta-item-text">发表于</span>
                  <time title="创建时间：2020-12-29 02:16:52" itemprop="dateCreated datePublished" datetime="2020-12-29T02:16:52+08:00">2020-12-29</time>
                </span>
                <span id="/30000.html" class="post-meta-item leancloud_visitors" data-flag-title="TypeScript教程一之基本类型" title="阅读次数">
                  <span class="post-meta-item-icon">
                    <i class="fa fa-eye"></i>
                  </span>
                  <span class="post-meta-item-text">阅读次数：</span>
                  <span class="leancloud-visitors-count"></span>
                </span>
                <span class="post-meta-item" title="本文字数">
                  <span class="post-meta-item-icon">
                    <i class="far fa-file-word"></i>
                  </span>
                  <span class="post-meta-item-text">本文字数：</span>
                  <span>9.1k</span>
                </span>
                <span class="post-meta-item" title="阅读时长">
                  <span class="post-meta-item-icon">
                    <i class="far fa-clock"></i>
                  </span>
                  <span class="post-meta-item-text">阅读时长 &asymp;</span>
                  <span>8 分钟</span>
                </span>
              </div>
            </article>
            <article itemscope itemtype="http://schema.org/Article" class="post-block index" lang="zh-CN">
              <link itemprop="mainEntityOfPage" href="https://cuiqingcai.com/23858.html">
              <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
                <meta itemprop="image" content="/images/avatar.png">
                <meta itemprop="name" content="崔庆才">
                <meta itemprop="description" content="崔庆才的个人站点，记录生活的瞬间，分享学习的心得。">
              </span>
              <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
                <meta itemprop="name" content="静觅">
              </span>
              <header class="post-header">
                <h2 class="post-title" itemprop="name headline">
                  <a class="label"> 技术杂谈 <i class="label-arrow"></i>
                  </a>
                  <a href="/23858.html" class="post-title-link" itemprop="url">腾讯云容器服务Docker容器存储爆满解决方案</a>
                </h2>
              </header>
              <div class="post-body" itemprop="articleBody">
                <div class="thumb">
                  <img itemprop="contentUrl" class="random">
                </div>
                <div class="excerpt">
                  <p>
                  <p>最近的服务都放到腾讯云上了，但是最近遇到了一个问题是 Docker 云磁盘满了，部署的适合提示 no space left 等等。</p>
                  <p>然后我就登录云主机看了下磁盘情况，好家伙：</p>
                  <figure class="highlight angelscript">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="symbol">ubuntu@</span>VM<span class="number">-0</span><span class="number">-2</span>-ubuntu:/var/lib/docker/containers$ df</span><br><span class="line">Filesystem     <span class="number">1</span>K-blocks    Used Available Use% Mounted on</span><br><span class="line">udev             <span class="number">3869584</span>       <span class="number">0</span>   <span class="number">3869584</span>   <span class="number">0</span>% /dev</span><br><span class="line">tmpfs             <span class="number">777376</span>   <span class="number">15124</span>    <span class="number">762252</span>   <span class="number">2</span>% /run</span><br><span class="line">/dev/vda1      <span class="number">103145380</span> <span class="number">9460508</span>  <span class="number">89390616</span>  <span class="number">10</span>% /</span><br><span class="line">tmpfs            <span class="number">3886864</span>      <span class="number">24</span>   <span class="number">3886840</span>   <span class="number">1</span>% /dev/shm</span><br><span class="line">tmpfs               <span class="number">5120</span>       <span class="number">0</span>      <span class="number">5120</span>   <span class="number">0</span>% /run/lock</span><br><span class="line">tmpfs            <span class="number">3886864</span>       <span class="number">0</span>   <span class="number">3886864</span>   <span class="number">0</span>% /sys/fs/cgroup</span><br><span class="line">/dev/vdb        <span class="number">10255636</span> <span class="number">10155252</span>   -  <span class="number">99</span>% /var/lib/docker</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>vdb 这个磁盘就是我的数据盘，里面放了容器数据，现在已经到了 99% 了，一共就 10G。</p>
                  <p>然后我就去腾讯云控制台搞了下数据盘的扩容，然后直接扩容到了 200G。</p>
                  <p>但是回过头来看了下磁盘还是 10G，一变不变。</p>
                  <p>但 fdisk 已经看到变了：</p>
                  <figure class="highlight yaml">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="string">ubuntu@VM-0-2-ubuntu:/var/lib/docker/containers$</span> <span class="string">sudo</span> <span class="string">fdisk</span> <span class="string">-l</span></span><br><span class="line"><span class="attr">Disk /dev/vda:</span> <span class="number">100</span> <span class="string">GiB,</span> <span class="number">107374182400</span> <span class="string">bytes,</span> <span class="number">209715200</span> <span class="string">sectors</span></span><br><span class="line"><span class="attr">Units:</span> <span class="string">sectors</span> <span class="string">of</span> <span class="number">1</span> <span class="string">*</span> <span class="number">512</span> <span class="string">=</span> <span class="number">512</span> <span class="string">bytes</span></span><br><span class="line"><span class="string">Sector</span> <span class="string">size</span> <span class="string">(logical/physical):</span> <span class="number">512</span> <span class="string">bytes</span> <span class="string">/</span> <span class="number">512</span> <span class="string">bytes</span></span><br><span class="line"><span class="string">I/O</span> <span class="string">size</span> <span class="string">(minimum/optimal):</span> <span class="number">512</span> <span class="string">bytes</span> <span class="string">/</span> <span class="number">512</span> <span class="string">bytes</span></span><br><span class="line"><span class="attr">Disklabel type:</span> <span class="string">dos</span></span><br><span class="line"><span class="attr">Disk identifier:</span> <span class="number">0x3fa1d255</span></span><br><span class="line"></span><br><span class="line"><span class="string">Device</span>     <span class="string">Boot</span> <span class="string">Start</span>       <span class="string">End</span>   <span class="string">Sectors</span>  <span class="string">Size</span> <span class="string">Id</span> <span class="string">Type</span></span><br><span class="line"><span class="string">/dev/vda1</span>  <span class="string">*</span>     <span class="number">2048</span> <span class="number">209715166</span> <span class="number">209713119</span>  <span class="string">100G</span> <span class="number">83</span> <span class="string">Linux</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="attr">Disk /dev/vdb:</span> <span class="number">200</span> <span class="string">GiB,</span> <span class="number">214748364800</span> <span class="string">bytes,</span> <span class="number">419430400</span> <span class="string">sectors</span></span><br><span class="line"><span class="attr">Units:</span> <span class="string">sectors</span> <span class="string">of</span> <span class="number">1</span> <span class="string">*</span> <span class="number">512</span> <span class="string">=</span> <span class="number">512</span> <span class="string">bytes</span></span><br><span class="line"><span class="string">Sector</span> <span class="string">size</span> <span class="string">(logical/physical):</span> <span class="number">512</span> <span class="string">bytes</span> <span class="string">/</span> <span class="number">512</span> <span class="string">bytes</span></span><br><span class="line"><span class="string">I/O</span> <span class="string">size</span> <span class="string">(minimum/optimal):</span> <span class="number">512</span> <span class="string">bytes</span> <span class="string">/</span> <span class="number">512</span> <span class="string">bytes</span></span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>这是因为之前的数据被格式化为了 ext4，但是新扩容的部分并没有。</p>
                  <p>问了腾讯云的工程师，这时候必须要重新格式化才能用上新的容量，没有好的解决方法。</p>
                  <p>最后的解决方案：</p>
                  <ul>
                    <li>将当前节点所有 Pod 驱逐到其他的节点。</li>
                    <li>当前节点退出集群然后配置磁盘，重新操作 mount 和格式化。（但是这里劝别折腾了，终究还是要格式化的。</li>
                    <li>把节点再加回来，这时候可以选重新格式化数据盘，mount 到 /var/lib/docker。</li>
                    <li>再把之前的 Pod 收回到本节点就好了。</li>
                  </ul>
                  <p>完毕。</p>
                  <p>感觉还是不完善啊，像 Azure Kubernetes 的扩容就方便多了，不用整这么多麻烦事。</p>
                  </p>
                </div>
              </div>
              <div class="post-meta">
                <span class="post-meta-item">
                  <span class="post-meta-item-icon">
                    <i class="far fa-user"></i>
                  </span>
                  <span class="post-meta-item-text">作者</span>
                  <span><a href="/authors/崔庆才" class="author" itemprop="url" rel="index">崔庆才</a></span>
                </span>
                <span class="post-meta-item">
                  <span class="post-meta-item-icon">
                    <i class="far fa-calendar"></i>
                  </span>
                  <span class="post-meta-item-text">发表于</span>
                  <time title="创建时间：2020-11-29 02:35:47" itemprop="dateCreated datePublished" datetime="2020-11-29T02:35:47+08:00">2020-11-29</time>
                </span>
                <span id="/23858.html" class="post-meta-item leancloud_visitors" data-flag-title="腾讯云容器服务Docker容器存储爆满解决方案" title="阅读次数">
                  <span class="post-meta-item-icon">
                    <i class="fa fa-eye"></i>
                  </span>
                  <span class="post-meta-item-text">阅读次数：</span>
                  <span class="leancloud-visitors-count"></span>
                </span>
                <span class="post-meta-item" title="本文字数">
                  <span class="post-meta-item-icon">
                    <i class="far fa-file-word"></i>
                  </span>
                  <span class="post-meta-item-text">本文字数：</span>
                  <span>1.3k</span>
                </span>
                <span class="post-meta-item" title="阅读时长">
                  <span class="post-meta-item-icon">
                    <i class="far fa-clock"></i>
                  </span>
                  <span class="post-meta-item-text">阅读时长 &asymp;</span>
                  <span>1 分钟</span>
                </span>
              </div>
            </article>
            <article itemscope itemtype="http://schema.org/Article" class="post-block index" lang="zh-CN">
              <link itemprop="mainEntityOfPage" href="https://cuiqingcai.com/23857.html">
              <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
                <meta itemprop="image" content="/images/avatar.png">
                <meta itemprop="name" content="崔庆才">
                <meta itemprop="description" content="崔庆才的个人站点，记录生活的瞬间，分享学习的心得。">
              </span>
              <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
                <meta itemprop="name" content="静觅">
              </span>
              <header class="post-header">
                <h2 class="post-title" itemprop="name headline">
                  <a class="label"> 技术杂谈 <i class="label-arrow"></i>
                  </a>
                  <a href="/23857.html" class="post-title-link" itemprop="url">Python之父和我成为同事了？！</a>
                </h2>
              </header>
              <div class="post-body" itemprop="articleBody">
                <div class="thumb">
                  <img itemprop="contentUrl" class="random">
                </div>
                <div class="excerpt">
                  <p>
                  <p>就昨天的时候，Python 之父 Guido 发了个推特，说自己觉得退休太无聊了，然后于是乎决定加入微软。</p>
                  <p><img src="https://qiniu.cuiqingcai.com/diqwk.jpg" alt=""></p>
                  <p>同时推特上大神 Anders Hejlsberg（Delphi、C# 和 TypeScript 之父）转发了推特，表示希望可以一起工作。</p>
                  <p><img src="https://qiniu.cuiqingcai.com/3nz48.png" alt=""></p>
                  <p>要知道，去年那会去年 10 月 30 日，Python 之父 Guido 宣布退休，当时他发推文说，“这件事感觉既苦涩又甜蜜：苦涩的是，我马上要离开 Dropbox，现在已经退休；甜蜜的是，在 Dropbox 做工程师期间，我学到很多，比如类型标注就来自这段经历。我会非常怀念在这里工作的日子。”</p>
                  <p>看到这个消息我既震惊又激动，Python 之父加入我司了？那我岂不是和他也算做同事了？哈哈哈。</p>
                  <p>当时我看到这个消息之后，第一时间就去公司的系统里面查了下，果真就查到了，这里放个图。</p>
                  <p><img src="https://qiniu.cuiqingcai.com/e1rl8.png" alt=""></p>
                  <p>他的 Title 叫 DISTINUISHED ENGINEER，这个 Title 可不是一般的牛逼，在微软，有这样的 Title 的人可是屈指可数的，DISTINUISHED 意思就是杰出的，非常牛逼的意思，能有这种 Title 的是为业界或公司做出过特别特别大贡献的，特别有影响力的，可能普通人在微软呆个二十多年都不一定能到这个地位。他的职级和 Report Line 就不说了，他距离微软 CEO 纳德拉只差 3 级，稍微形象点说就是对标阿里 P11 或者 P12 的位置吧。</p>
                  <p>他的部门就直接写了 Python and Tools for AI，和 AI 相关，同时 Guido 又这么热爱开源，微软也在一直拥抱开源，期待 Python 之父将来不久之后又出新的杰作吧。</p>
                  <p>要知道 Python 之父 Guido 已经 64 岁了，或许大佬就是大佬吧，退休了感觉无聊，就来微软来玩玩。怎么说呢？他这个地位就是类似达成一些自我追求和实现自己的一些价值，顺便解解闷，这种境界完全不是我们能比的了。反过来想想中国这个环境，多少人都是用代码来换取一份工作谋求生存，然后 35 岁干不动了可能就被辞退。本来想展开说说的，但是感觉说来都是痛，就不多说了，希望我将来不会为生活所迫，能够自由地继续追求自己热爱的东西。</p>
                  <p>另外本想说说 Guido 的履历的，但看到其他的一些文章已经整理得挺好了，我就不再重复了，大家想了解更多的话可以去看看 <a href="https://mp.weixin.qq.com/s/ZQJClbYiKP5cAnKjB_ZfUg。" target="_blank" rel="noopener">https://mp.weixin.qq.com/s/ZQJClbYiKP5cAnKjB_ZfUg。</a></p>
                  <p>总之，我就是来宣布这个和 Python 之父成为“同事”的开心的消息，值得纪念下，然后顺便期待下 Python 之父将来出新的杰作！</p>
                  </p>
                </div>
              </div>
              <div class="post-meta">
                <span class="post-meta-item">
                  <span class="post-meta-item-icon">
                    <i class="far fa-user"></i>
                  </span>
                  <span class="post-meta-item-text">作者</span>
                  <span><a href="/authors/崔庆才" class="author" itemprop="url" rel="index">崔庆才</a></span>
                </span>
                <span class="post-meta-item">
                  <span class="post-meta-item-icon">
                    <i class="far fa-calendar"></i>
                  </span>
                  <span class="post-meta-item-text">发表于</span>
                  <time title="创建时间：2020-11-14 23:28:24" itemprop="dateCreated datePublished" datetime="2020-11-14T23:28:24+08:00">2020-11-14</time>
                </span>
                <span id="/23857.html" class="post-meta-item leancloud_visitors" data-flag-title="Python之父和我成为同事了？！" title="阅读次数">
                  <span class="post-meta-item-icon">
                    <i class="fa fa-eye"></i>
                  </span>
                  <span class="post-meta-item-text">阅读次数：</span>
                  <span class="leancloud-visitors-count"></span>
                </span>
                <span class="post-meta-item" title="本文字数">
                  <span class="post-meta-item-icon">
                    <i class="far fa-file-word"></i>
                  </span>
                  <span class="post-meta-item-text">本文字数：</span>
                  <span>1k</span>
                </span>
                <span class="post-meta-item" title="阅读时长">
                  <span class="post-meta-item-icon">
                    <i class="far fa-clock"></i>
                  </span>
                  <span class="post-meta-item-text">阅读时长 &asymp;</span>
                  <span>1 分钟</span>
                </span>
              </div>
            </article>
            <article itemscope itemtype="http://schema.org/Article" class="post-block index" lang="zh-CN">
              <link itemprop="mainEntityOfPage" href="https://cuiqingcai.com/23859.html">
              <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
                <meta itemprop="image" content="/images/avatar.png">
                <meta itemprop="name" content="崔庆才">
                <meta itemprop="description" content="崔庆才的个人站点，记录生活的瞬间，分享学习的心得。">
              </span>
              <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
                <meta itemprop="name" content="静觅">
              </span>
              <header class="post-header">
                <h2 class="post-title" itemprop="name headline">
                  <a class="label"> 技术杂谈 <i class="label-arrow"></i>
                  </a>
                  <a href="/23859.html" class="post-title-link" itemprop="url">二次封装requests，构造通用的请求函数</a>
                </h2>
              </header>
              <div class="post-body" itemprop="articleBody">
                <div class="thumb">
                  <img itemprop="contentUrl" class="random">
                </div>
                <div class="excerpt">
                  <p>
                  <p>本章将告诉你该如何去对request模块进行二次封装，暂时并不会告诉你HTTP协议及原理、URL等相关。当然你会使用然后在来阅读此文章一定会另有所获。我已经迫不及待要告诉你这个小秘密，以及想与你交流了。没时间解释了，快来一起和我一起探讨相关的内容吧</p>
                  <p><a href="https://requests.readthedocs.io/zh_CN/latest/#requests-http" target="_blank" rel="noopener">官方文档</a>对requests的定义为：Requests 唯一的一个<strong>非转基因</strong>的 Python HTTP 库，人类可以安全享用。</p>
                  <p>使用Python写做爬虫的小伙伴一定使用过requests这个模块，初入爬虫的小伙伴也一定写过N个重复的requests，这是你的疑问。当然也一直伴随着我，最近在想对requests如何进行封装一下，让他支持支持通用的函数。若需要使用，直接调用即可。</p>
                  <p>那么问题来了，如果要写个供自己使用通用的请求函数将会有几个问题</p>
                  <ul>
                    <li>requests的请求方式(GET\POST\INPUT等等)</li>
                    <li>智能识别网站的编码，避免出现乱码</li>
                    <li>支持文本、二进制(图片、视频等为二进制内容)</li>
                    <li>以及还需要傻瓜一点，那就是网站的Ua(Ua:User-Agent，基本上网站都会验证接受到请求的Ua。来初步判断是爬虫还是用户)</li>
                  </ul>
                  <p>那么咱们就针对以上问题开干吧</p>
                  <h2 id="Requests的安装"><a href="#Requests的安装" class="headerlink" title="Requests的安装"></a>Requests的安装</h2>
                  <p>在确保python环境搭建完成后直接使用pip或者conda命令进行安装，安装命令如下：</p>
                  <figure class="highlight sh">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line">pip install requests</span><br><span class="line">conda install requests</span><br><span class="line"></span><br><span class="line"><span class="comment"># 或者下载过慢点话，可以使用国内的pip镜像源，例如:</span></span><br><span class="line">pip install requests -i  https://pypi.tuna.tsinghua.edu.cn/simple/</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>安装完成后，效果图如下：</p>
                  <p><img src="https://tva1.sinaimg.cn/large/0081Kckwgy1gkmppwcd62j325008g0w1.jpg" alt=""></p>
                  <h2 id="初探requests基本使用"><a href="#初探requests基本使用" class="headerlink" title="初探requests基本使用"></a>初探requests基本使用</h2>
                  <p>HTTP 中最常见的请求之一就是 GET 请求，下面我们来详细了解利用 requests 库构建 GET 请求的方法。</p>
                  <figure class="highlight python">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="keyword">import</span> requests</span><br><span class="line"></span><br><span class="line">response = requests.get(<span class="string">'http://httpbin.org/get'</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 响应状态码</span></span><br><span class="line">print(<span class="string">"response.status_code:"</span>, response.status_code)</span><br><span class="line"><span class="comment"># 响应头</span></span><br><span class="line">print(<span class="string">"response.headers:"</span>, response.headers)</span><br><span class="line"><span class="comment"># 响应请求头</span></span><br><span class="line">print(<span class="string">"response.request.headers:"</span>, response.request.headers)</span><br><span class="line"><span class="comment"># 响应二进制内容</span></span><br><span class="line">print(<span class="string">"response.content:"</span>, response.content)</span><br><span class="line"><span class="comment"># 响应文本</span></span><br><span class="line">print(<span class="string">"response.text"</span>, response.text)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 返回如下</span></span><br><span class="line">response.status_code: <span class="number">200</span></span><br><span class="line">response.headers: &#123;<span class="string">'Date'</span>: <span class="string">'Thu, 12 Nov 2020 13:38:05 GMT'</span>, <span class="string">'Content-Type'</span>: <span class="string">'application/json'</span>, <span class="string">'Content-Length'</span>: <span class="string">'306'</span>, <span class="string">'Connection'</span>: <span class="string">'keep-alive'</span>, <span class="string">'Server'</span>: <span class="string">'gunicorn/19.9.0'</span>, <span class="string">'Access-Control-Allow-Origin'</span>: <span class="string">'*'</span>, <span class="string">'Access-Control-Allow-Credentials'</span>: <span class="string">'true'</span>&#125;</span><br><span class="line">response.request.headers: &#123;<span class="string">'User-Agent'</span>: <span class="string">'python-requests/2.24.0'</span>, <span class="string">'Accept-Encoding'</span>: <span class="string">'gzip, deflate'</span>, <span class="string">'Accept'</span>: <span class="string">'*/*'</span>, <span class="string">'Connection'</span>: <span class="string">'keep-alive'</span>&#125;</span><br><span class="line">response.content: <span class="string">b'&#123;\n  "args": &#123;&#125;, \n  "headers": &#123;\n    "Accept": "*/*", \n    "Accept-Encoding": "gzip, deflate", \n    "Host": "httpbin.org", \n    "User-Agent": "python-requests/2.24.0", \n    "X-Amzn-Trace-Id": "Root=1-5fad3abd-7516d60b3e951824687a50d8"\n  &#125;, \n  "origin": "116.162.2.166", \n  "url": "http://httpbin.org/get"\n&#125;\n'</span></span><br><span class="line">&#123;</span><br><span class="line">  <span class="string">"args"</span>: &#123;&#125;,</span><br><span class="line">  <span class="string">"headers"</span>: &#123;</span><br><span class="line">    <span class="string">"Accept"</span>: <span class="string">"*/*"</span>,</span><br><span class="line">    <span class="string">"Accept-Encoding"</span>: <span class="string">"gzip, deflate"</span>,</span><br><span class="line">    <span class="string">"Host"</span>: <span class="string">"httpbin.org"</span>,</span><br><span class="line">    <span class="string">"User-Agent"</span>: <span class="string">"python-requests/2.24.0"</span>,</span><br><span class="line">    <span class="string">"X-Amzn-Trace-Id"</span>: <span class="string">"Root=1-5fad3abd-7516d60b3e951824687a50d8"</span></span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="string">"origin"</span>: <span class="string">"116.162.2.166"</span>,</span><br><span class="line">  <span class="string">"url"</span>: <span class="string">"http://httpbin.org/get"</span></span><br><span class="line">&#125;</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>requests基本使用已经经过简单的测试了，是否有一点点feel呢？接下来我们直接将它封装为一个函数以供随时调用</p>
                  <p>示例如下</p>
                  <figure class="highlight python">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="keyword">import</span> requests</span><br><span class="line"></span><br><span class="line">urls = <span class="string">'http://httpbin.org/get'</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">downloader</span><span class="params">(url, headers=None)</span>:</span></span><br><span class="line">    response = requests.get(url, headers=headers)</span><br><span class="line">    <span class="keyword">return</span> response</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">print(<span class="string">"downloader.status_code:"</span>, downloader(url=urls).status_code)</span><br><span class="line">print(<span class="string">"downloader.headers:"</span>, downloader(url=urls).headers)</span><br><span class="line">print(<span class="string">"downloader.request.headers:"</span>, downloader(url=urls).request.headers)</span><br><span class="line">print(<span class="string">"downloader.content:"</span>, downloader(url=urls).content)</span><br><span class="line">print(<span class="string">"downloader.text"</span>, downloader(url=urls).text)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 返回效果如上所示，此处省略</span></span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>以上我们就把，请求方法封装成了一个函数。将基本的url，headers以形参的方式暴露出来，我们只需传入需要请求的url即可发起请求，至此一个简单可复用的请求方法咱们就完成啦。</p>
                  <p>完～～～</p>
                  <p>以上照顾新手的就基本完成了，接下来我们搞点真家伙。</p>
                  <h2 id="二次封装"><a href="#二次封装" class="headerlink" title="二次封装"></a>二次封装</h2>
                  <h3 id="请求函数的封装"><a href="#请求函数的封装" class="headerlink" title="请求函数的封装"></a>请求函数的封装</h3>
                  <p>由于请求方式并不一定(有可能是GET也有可能是POST)，所以我们并不能<code>智能</code>的确定它是什么方式发送请求的。</p>
                  <p>Requests中request方法以及帮我们实现了这个方法。我们将他的请求方式暴露出来，写法如下：</p>
                  <figure class="highlight python">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line">urls = <span class="string">'http://httpbin.org/get'</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">downloader</span><span class="params">(url, method=None, headers=None)</span>:</span></span><br><span class="line">    _method = <span class="string">"GET"</span> <span class="keyword">if</span> <span class="keyword">not</span> method <span class="keyword">else</span> method</span><br><span class="line">    response = requests.request(url, method=_method, headers=headers)</span><br><span class="line">    <span class="keyword">return</span> response</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">print(<span class="string">"downloader.status_code:"</span>, downloader(url=urls).status_code)</span><br><span class="line">print(<span class="string">"downloader.headers:"</span>, downloader(url=urls).headers)</span><br><span class="line">print(<span class="string">"downloader.request.headers:"</span>, downloader(url=urls).request.headers)</span><br><span class="line">print(<span class="string">"downloader.content:"</span>, downloader(url=urls).content)</span><br><span class="line">print(<span class="string">"downloader.text"</span>, downloader(url=urls).text)</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>由于大部分都是GET方法，所以我们定义了一个默认的请求方式。如果需要修改请求方式，只需在调用时传入相对应的方法即可。例如我们可以这样</p>
                  <figure class="highlight python">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line">downloader(urls, method=<span class="string">"POST"</span>)</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <h3 id="文本编码问题"><a href="#文本编码问题" class="headerlink" title="文本编码问题"></a>文本编码问题</h3>
                  <p>解决由于request的误差判断而造成解码错误，而得到乱码。</p>
                  <p>此误差造成的原因是可能是响应头的<code>Accept-Encoding</code>，另一个是识别错误</p>
                  <figure class="highlight python">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="comment"># 查看响应编码</span></span><br><span class="line">response.encoding</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>此时我们需要借用Python中C语言编写的<code>cchardet</code>这个包来识别响应文本的编码。安装它</p>
                  <figure class="highlight sh">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line">pip install cchardet -i  https://pypi.tuna.tsinghua.edu.cn/simple/</span><br><span class="line"><span class="comment"># 如果pip直接安装失败的话，直接用清华源的镜像。</span></span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <figure class="highlight python">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="comment"># 实现智能版的解码：如下</span></span><br><span class="line">encoding = cchardet.detect(response.content)[<span class="string">'encoding'</span>]</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">downloader</span><span class="params">(url, method=None, headers=None)</span>:</span></span><br><span class="line">    _method = <span class="string">"GET"</span> <span class="keyword">if</span> <span class="keyword">not</span> method <span class="keyword">else</span> method</span><br><span class="line">    response = requests.request(url, method=_method, headers=headers)</span><br><span class="line">    encoding = cchardet.detect(response.content)[<span class="string">'encoding'</span>]</span><br><span class="line">    <span class="keyword">return</span> response.content.decode(encoding)</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <h3 id="区分二进制与文本的解析"><a href="#区分二进制与文本的解析" class="headerlink" title="区分二进制与文本的解析"></a>区分二进制与文本的解析</h3>
                  <p>在下载图片、视频等需获取到其二进制内容。而下载网页文本需要进行encode。</p>
                  <p>同理，我们只需要将一个标志传进去，从而达到分辨的的效果。例如这样</p>
                  <figure class="highlight python">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">downloader</span><span class="params">(url, method=None, headers=None, binary=False)</span>:</span></span><br><span class="line">    _method = <span class="string">"GET"</span> <span class="keyword">if</span> <span class="keyword">not</span> method <span class="keyword">else</span> method</span><br><span class="line">    response = requests.request(url, method=_method, headers=headers)</span><br><span class="line">    encoding = cchardet.detect(response.content)[<span class="string">'encoding'</span>]</span><br><span class="line">    <span class="keyword">return</span> response.content <span class="keyword">if</span> binary <span class="keyword">else</span> response.content.decode(encoding)</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <h3 id="默认Ua"><a href="#默认Ua" class="headerlink" title="默认Ua"></a>默认Ua</h3>
                  <p>在很多时候，我们拿ua又是复制。又是加引号构建key-value格式。这样有时候仅仅用requests做个测试。就搞的麻烦的很。而且请求过多了，直接就被封IP了。没有自己的ip代理，没有钱又时候还真有点感觉玩不起爬虫。</p>
                  <p>为了减少被封禁IP的概率什么的，我们添加个自己的Ua池。Ua池的原理很简单，内部就是采用随机的Ua，从而减少被发现的<code>概率</code>.至于为什么可以达到这这样的效果，在这里仅作简单介绍。详细可能要从计算机网络原理说起。</p>
                  <p>结论就是你一个公司里大多采用的都是同一个<code>外网</code>ip去访问目标网址。那么就意味着可能你们公司有N个人使用同一个ip去访问目标网址。而封禁做区分的一般由ip访问频率和浏览器的指纹和在一起的什么鬼东东。简单理解为Ua+ip访问频率达到峰值，你IP就对方关小黑屋了。</p>
                  <p>构建自己的ua池，去添加默认的请求头，</p>
                  <p>Ua有很多，这里就不放出来了，如果有兴趣可以直接去<a href="https://github.com/PowerSpider/PowerSpider/tree/dev" target="_blank" rel="noopener">源码</a>里面拿。直接说原理：构造很多个Ua，然后随机取用。从而降低这个同一访问频率：同时也暴露端口方便你自己传入header</p>
                  <figure class="highlight python">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="keyword">from</span> powerspider.tools.Ua <span class="keyword">import</span> ua</span><br><span class="line"><span class="keyword">import</span> requests</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">downloader</span><span class="params">(url, method=None, header=None, binary=False)</span>:</span></span><br><span class="line">    _headers = header <span class="keyword">if</span> header <span class="keyword">else</span> &#123;<span class="string">'User-Agent'</span>: ua()&#125;</span><br><span class="line">    _method = <span class="string">"GET"</span> <span class="keyword">if</span> <span class="keyword">not</span> method <span class="keyword">else</span> method</span><br><span class="line">    response = requests.request(url, method=_method, headers=_headers)</span><br><span class="line">    encoding = cchardet.detect(response.content)[<span class="string">'encoding'</span>]</span><br><span class="line">    <span class="keyword">return</span> response.content <span class="keyword">if</span> binary <span class="keyword">else</span> response.content.decode(encoding)</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>那么基本的文件都已经解决了，不过还不完美。异常处理，错误重试，日志什么都没。这怎么行呢。活既然干了，那就干的漂漂亮亮的。</p>
                  <p>来让我们加入进来这些东西</p>
                  <figure class="highlight python">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="keyword">import</span> cchardet</span><br><span class="line"><span class="keyword">from</span> retrying <span class="keyword">import</span> retry</span><br><span class="line"><span class="keyword">from</span> powerspider <span class="keyword">import</span> logger</span><br><span class="line"><span class="keyword">from</span> powerspider.tools.Ua <span class="keyword">import</span> ua</span><br><span class="line"><span class="keyword">from</span> requests <span class="keyword">import</span> request, RequestException</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="meta">@retry(stop_max_attempt_number=3, retry_on_result=lambda x: x is None, wait_fixed=2000)</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">downloader</span><span class="params">(url, method=None, header=None, timeout=None, binary=False, **kwargs)</span>:</span></span><br><span class="line">    logger.info(<span class="string">f'Scraping <span class="subst">&#123;url&#125;</span>'</span>)</span><br><span class="line">    _header = &#123;<span class="string">'User-Agent'</span>: ua()&#125;</span><br><span class="line">    _maxTimeout = timeout <span class="keyword">if</span> timeout <span class="keyword">else</span> <span class="number">5</span></span><br><span class="line">    _headers = header <span class="keyword">if</span> header <span class="keyword">else</span> _header</span><br><span class="line">    _method = <span class="string">"GET"</span> <span class="keyword">if</span> <span class="keyword">not</span> method <span class="keyword">else</span> method</span><br><span class="line">    <span class="keyword">try</span>:</span><br><span class="line">        response = request(method=_method, url=url, headers=_headers, **kwargs)</span><br><span class="line">        encoding = cchardet.detect(response.content)[<span class="string">'encoding'</span>]</span><br><span class="line">        <span class="keyword">if</span> response.status_code == <span class="number">200</span>:</span><br><span class="line">            <span class="keyword">return</span> response.content <span class="keyword">if</span> binary <span class="keyword">else</span> response.content.decode(encoding)</span><br><span class="line">        <span class="keyword">elif</span> <span class="number">200</span> &lt; response.status_code &lt; <span class="number">400</span>:</span><br><span class="line">            logger.info(<span class="string">f"Redirect_URL: <span class="subst">&#123;response.url&#125;</span>"</span>)</span><br><span class="line">        logger.error(<span class="string">'Get invalid status code %s while scraping %s'</span>, response.status_code, url)</span><br><span class="line">    <span class="keyword">except</span> RequestException <span class="keyword">as</span> e:</span><br><span class="line">        logger.error(<span class="string">f'Error occurred while scraping <span class="subst">&#123;url&#125;</span>, Msg: <span class="subst">&#123;e&#125;</span>'</span>, exc_info=<span class="literal">True</span>)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">'__main__'</span>:</span><br><span class="line">    print(downloader(<span class="string">"https://www.baidu.com/"</span>, <span class="string">"GET"</span>))</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>至此，我们的对Requests二次封装，构造通用的请求函数就已经完成了。</p>
                  <p>源码地址：<a href="https://github.com/PowerSpider/PowerSpider/tree/dev" target="_blank" rel="noopener">https://github.com/PowerSpider/PowerSpider/tree/dev</a></p>
                  <p>期待下次再见</p>
                  </p>
                </div>
              </div>
              <div class="post-meta">
                <span class="post-meta-item">
                  <span class="post-meta-item-icon">
                    <i class="far fa-user"></i>
                  </span>
                  <span class="post-meta-item-text">作者</span>
                  <span><a href="/authors/Payne" class="author" itemprop="url" rel="index">Payne</a></span>
                </span>
                <span class="post-meta-item">
                  <span class="post-meta-item-icon">
                    <i class="far fa-calendar"></i>
                  </span>
                  <span class="post-meta-item-text">发表于</span>
                  <time title="创建时间：2020-11-12 23:42:51" itemprop="dateCreated datePublished" datetime="2020-11-12T23:42:51+08:00">2020-11-12</time>
                </span>
                <span id="/23859.html" class="post-meta-item leancloud_visitors" data-flag-title="二次封装requests，构造通用的请求函数" title="阅读次数">
                  <span class="post-meta-item-icon">
                    <i class="fa fa-eye"></i>
                  </span>
                  <span class="post-meta-item-text">阅读次数：</span>
                  <span class="leancloud-visitors-count"></span>
                </span>
                <span class="post-meta-item" title="本文字数">
                  <span class="post-meta-item-icon">
                    <i class="far fa-file-word"></i>
                  </span>
                  <span class="post-meta-item-text">本文字数：</span>
                  <span>6.5k</span>
                </span>
                <span class="post-meta-item" title="阅读时长">
                  <span class="post-meta-item-icon">
                    <i class="far fa-clock"></i>
                  </span>
                  <span class="post-meta-item-text">阅读时长 &asymp;</span>
                  <span>6 分钟</span>
                </span>
              </div>
            </article>
            <article itemscope itemtype="http://schema.org/Article" class="post-block index" lang="zh-CN">
              <link itemprop="mainEntityOfPage" href="https://cuiqingcai.com/23855.html">
              <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
                <meta itemprop="image" content="/images/avatar.png">
                <meta itemprop="name" content="崔庆才">
                <meta itemprop="description" content="崔庆才的个人站点，记录生活的瞬间，分享学习的心得。">
              </span>
              <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
                <meta itemprop="name" content="静觅">
              </span>
              <header class="post-header">
                <h2 class="post-title" itemprop="name headline">
                  <a class="label"> 技术杂谈 <i class="label-arrow"></i>
                  </a>
                  <a href="/23855.html" class="post-title-link" itemprop="url">华为云CloudIDE带你实现云上编码</a>
                </h2>
              </header>
              <div class="post-body" itemprop="articleBody">
                <div class="thumb">
                  <img itemprop="contentUrl" class="random">
                </div>
                <div class="excerpt">
                  <p>
                  <p>前阵子有个朋友问我一个 Python 相关的问题，然后我把解决方案简单用代码写了一下发给他，结果他说跑不起来，我就很纳闷，确认了下他说 Python 库也都装了，但是运行的时候还是会报库找不到。果不其然，经过一段时间沟通发现，它的机器上装了两个 Python 环境，装 Python 库的时候是用的 pip 安装的，它对应了一个 Python 环境，但是运行的时候却是用的使用的 python3 命令却是对应另外一个 Python 环境，理所当然就跑不通了。这个问题其实挺常见的，有时候跟对方说检查下 Python 环境路径什么的，但是对方有时候并不知道怎么做，或者直接得再告诉他用 <code>python3 -m pip install ...</code> 命令来装包。</p>
                  <p>另外我还有个需求是，我写了一些代码，想直接把运行结果和代码发给别人看，一种方法可以直接借助于 GitHub，代码放上去，然后让对方 Clone 下来再运行。对方也得配置下相关的环境才能正确跑起来。另一种方法则是打包 Docker 镜像，但是这也得额外花一些时间。有没有更好的方案解决这个问题呢？</p>
                  <p>上面这就是两个问题：</p>
                  <ul>
                    <li>环境不一致的问题</li>
                    <li>环境共享的问题</li>
                  </ul>
                  <p>这俩问题有通用的解决方案吗？有！答案就是云 IDE。有了云 IDE，不仅以上两个问题可以解决，甚至都不用自己配置开发环境了，我们只需要一个浏览器就能在线编辑代码，同时这个 IDE 还能分享给他人，他人打开之后，看到的就是和我一模一样的内容，甚至还可以看到我正在编写代码的实时效果。</p>
                  <p>美哉美哉！</p>
                  <p>今天就给大家介绍一款云 IDE，是华为家的，叫做「华为云CloudIDE」，我试用了一下感觉还不错，它的官方介绍页面是这样的：</p>
                  <p><img src="https://qiniu.cuiqingcai.com/mqq3y.png" alt="image-20201111005857785"></p>
                  <p>官方介绍如下：</p>
                  <blockquote>
                    <p>通过华为云CloudIDE，您仅需一个浏览器就可以编辑、调试、运行您的代码。</p>
                    <p>开发环境通常包括各种配置文件、特定的语言、框架版本、以及其他个人设备等等一系列个人配置。当您开发一个新的项目或者测试一些程序时，不得不对已有的个人配置做相应的调整。或者，您可以通过CloudIDE将个人的偏好设置转移到云端。CloudIDE将存储项目设置，实现您与他人共享，并通过浏览器授予访问的权限。您可以将所有文件保存在云环境中，并通过各种访问设备操作管理它们。开发环境在云端，您可以实现代码阅读、编写、调试、运行，也可以将代码存入代码仓库，随时、随地、随心！</p>
                  </blockquote>
                  <p>和我刚才说的就是一样的，利用它我们可以解决诸多问题：如环境配置、环境统一、环境共享的问题，同时我们还可以随时随地编辑代码，丝毫不受机器的限制，上云之后，一切都是那么方便。</p>
                  <p>好，这里我就带大家来体验下「华为云CloudIDE」吧。</p>
                  <p>首先，目前「华为云CloudIDE」是可以免费体验的，每个人每天有 120 分钟的免费体验时间，如果要获得更好的体验可以创建付费实例。</p>
                  <p>目前免费体验需要有这些规定：</p>
                  <p>尊敬的用户，您已经开通CloudIDE服务，免费体验需要遵守如下约定：</p>
                  <ul>
                    <li>每天的免费体验时间为120分钟，少于5分钟不能创建新的体验；</li>
                    <li>每个实例可使用时长为60分钟，60分钟后，实例将会被删除，并且数据将会被删除；</li>
                    <li>同一时间只能体验一个实例，打开第二个实例将会自动关闭第一个实例；</li>
                    <li>免费体验不能保证最佳使用体验，您可能需要排队等候，付费使用可以获得更好的体验</li>
                  </ul>
                  <p>完全没问题，体验完全足够了。</p>
                  <p>我这里操作的 URL 是 <a href="https://devcloud.cn-north-4.huaweicloud.com/cloudide/trial，大家可以注册个华为云账号就能看到对应的入口页面了，就是上文发的图。" target="_blank" rel="noopener">https://devcloud.cn-north-4.huaweicloud.com/cloudide/trial，大家可以注册个华为云账号就能看到对应的入口页面了，就是上文发的图。</a></p>
                  <p>由于我对 Python 比较熟悉，那么我就来体验一个 Python 环境吧，找到下方的 Python 环境，然后点击「免费体验」。</p>
                  <p>这时候环境就会变成「启动中」的状态，如图所示：</p>
                  <p><img src="https://qiniu.cuiqingcai.com/0egrr.png" alt="image-20201111010644754"></p>
                  <p>然后接下来我们就会进入到云 IDE 的环境，等待一顿初始化之后之后，我们就可以看到如下页面，如图所示：</p>
                  <p><img src="https://qiniu.cuiqingcai.com/r9k3g.png" alt="image-20201111010740454"></p>
                  <p>嗯？有没有熟悉的感觉？</p>
                  <p>没错，这和 VS Code 可太像了，简直就是一个在线版的 VS Code。不过仔细看看，其实还是有些不一样的，比如左上角的 Logo，插件仓库以及一些菜单选项。可以说是 VS Code 的魔改版。</p>
                  <p>我们看下左侧栏其他的菜单，搜索、版本控制、调试没啥好说的，看看插件仓库吧，打开之后是这样的：</p>
                  <p><img src="https://qiniu.cuiqingcai.com/zvatx.png" alt="image-20201111011151570"></p>
                  <p>这里我们可以看到「华为云CloudIDE」已经为我们预装了一些插件，如 Python。另外下方还有一些推荐的插件，例如 Huawei Cloud Toolkit，这些插件的安装方式和 VS Code 是一模一样的。</p>
                  <p>接下来我们再看看菜单的一些配置，随便挑几个看看吧：</p>
                  <p><img src="https://qiniu.cuiqingcai.com/mljvc.png" alt="image-20201111011434518"></p>
                  <p><img src="https://qiniu.cuiqingcai.com/ztzn9.png" alt="image-20201111011453092"></p>
                  <p>几乎所有功能菜单和 VS Code 是一样的，不过「华为云CloudIDE」添加了一些入口，比如 Close Instance 等等，点了之后就会关闭当前云 IDE 实例。</p>
                  <p>OK，接下来我们再回到代码看看，看看它给初始化了个什么，代码结构是这样的：</p>
                  <p><img src="https://qiniu.cuiqingcai.com/etn5w.png" alt="image-20201111011717465"></p>
                  <p>就是一个基本的 Flask 的 Hello World。</p>
                  <p>那来跑跑试试吧，点击右上角的运行按钮，如图所示：</p>
                  <p><img src="https://qiniu.cuiqingcai.com/3eogy.png" alt="image-20201111011824402"></p>
                  <p>哦，居然报错了，内容如下：</p>
                  <p><img src="https://qiniu.cuiqingcai.com/4ly2x.png" alt="image-20201111011856800"></p>
                  <p>这里报错说找不到 flask 这个包，那很明显就是没安装了，正好我们可以看到 requirements.txt 定义了相关的依赖环境，那我们来手动安装下吧。</p>
                  <p>在当前命令行下输入：</p>
                  <figure class="highlight cmake">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line">pip3 <span class="keyword">install</span> -r requirements.txt</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>运行结果类似如下：</p>
                  <p><img src="https://qiniu.cuiqingcai.com/75k2m.png" alt="image-20201111012030928"></p>
                  <p>看起来不错，另外可以观察到它是从 <a href="https://repo.huaweicloud.com/repository/pypi/" target="_blank" rel="noopener">https://repo.huaweicloud.com/repository/pypi/</a> 这里下载的 Python 包，速度也挺快的。简直是意外收获呢，又发现了一个不错的 Pypi 加速镜像。</p>
                  <p>顺便看看 pip.conf 配置吧：</p>
                  <figure class="highlight stata">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="keyword">cat</span> ~/.pip/pip.<span class="keyword">conf</span></span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>结果如下：</p>
                  <figure class="highlight pgsql">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line">[<span class="keyword">global</span>]</span><br><span class="line"><span class="keyword">index</span>-url = https://repo.huaweicloud.com/repository/pypi/simple</span><br><span class="line"><span class="keyword">trusted</span>-host = repo.huaweicloud.com</span><br><span class="line">timeout = <span class="number">120</span></span><br><span class="line">extra-<span class="keyword">index</span>-url = https://obs-workspace<span class="number">-20180810.</span>obs.cn-north<span class="number">-1.</span>myhuaweicloud.com/pypi/simple</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>一目了然，可以看到 pip 全局配置了一个加速镜像，index-url 配置为了 <a href="https://repo.huaweicloud.com/repository/pypi/simple，这个是可以公开访问的，所以以后" target="_blank" rel="noopener">https://repo.huaweicloud.com/repository/pypi/simple，这个是可以公开访问的，所以以后</a></p>
                  <p>我们装包的时候就可以这么来装了：</p>
                  <figure class="highlight awk">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line">pip3 install requests -i https:<span class="regexp">//</span>repo.huaweicloud.com<span class="regexp">/repository/</span>pypi<span class="regexp">/simple</span></span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>速度还是挺不错的，美滋滋，意外收获。</p>
                  <p>OK，切回正题，这时候我们已经装完环境了，重新运行 app.py，这时候就可以发现运行成功了，结果类似如下：</p>
                  <p><img src="https://qiniu.cuiqingcai.com/u2vph.png" alt="image-20201111012729299"></p>
                  <p>可以看到它就在 8080 端口上运行了一个服务，那咋访问呢？</p>
                  <p>在运行的同时，还弹出了这么一个窗口，如图所示：</p>
                  <p><img src="https://qiniu.cuiqingcai.com/w80pr.png" alt="image-20201111012846946"></p>
                  <p>似乎是提示我们可以注册一个外部端口将服务暴露出去，我们点击 Register 和 OK。</p>
                  <p>接下来 OK 按钮就变成了 Access 按钮，如图所示：</p>
                  <p><img src="https://qiniu.cuiqingcai.com/6qotw.png" alt="image-20201111013057453"></p>
                  <p>还带了一个二维码和 Copy 按钮，我们 Copy 一下看看，我 Copy 之后的 URL 是 <a href="https://sermgcaktl-8080-cce-5.lf.templink.dev/，然后我在浏览器中打开，显示如下：" target="_blank" rel="noopener">https://sermgcaktl-8080-cce-5.lf.templink.dev/，然后我在浏览器中打开，显示如下：</a></p>
                  <p><img src="https://qiniu.cuiqingcai.com/u1dd9.png" alt="image-20201111013157227"></p>
                  <p>很不错啊，这是自动给我们生成了一个域名，然后还把服务暴露出去可供访问了，挺好。</p>
                  <p>接下来我们再看看 Workspace 吧，切换下代码文件夹，点击 File - Open ，可以看到如下页面：</p>
                  <p><img src="https://qiniu.cuiqingcai.com/7mnj2.png" alt="image-20201111013747428"></p>
                  <p>可以看到当前打开的是 python3-sample 这个文件夹，那能换其他文件夹吗？我在上方输入个根目录 / 看看，结果如图所示：</p>
                  <p><img src="https://qiniu.cuiqingcai.com/bp0jm.png" alt="image-20201111013852795"></p>
                  <p>出现了熟悉的 Linux 文件树结构，那可以断定这其实就是一个 Linux 环境了，那岂不是干啥事都行了。</p>
                  <p>找到 /home/user/projects 目录，看起来是用来专门存放项目的目录。</p>
                  <p>另外我再试试能否随便打开一个 GitHub 上的项目吧，比如在控制台进入刚才这个目录，然后 Clone 一个项目，命令如下：</p>
                  <figure class="highlight awk">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line">cd <span class="regexp">/home/u</span>ser<span class="regexp">/projects/</span></span><br><span class="line">git clone https:<span class="regexp">//gi</span>thub.com<span class="regexp">/Python3WebSpider/</span>ScrapyTutorial.git</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>OK，简单 Clone 了一个 Scrapy 项目，成功！如图所示：</p>
                  <p><img src="https://qiniu.cuiqingcai.com/gcp5p.png" alt="image-20201111014223373"></p>
                  <p>然后打开下这个项目，如图所示：</p>
                  <p><img src="https://qiniu.cuiqingcai.com/iv7as.png" alt="image-20201111015026872"></p>
                  <p>打开 Terminal，安装下依赖：</p>
                  <figure class="highlight mipsasm">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line">pip3 <span class="keyword">install </span><span class="keyword">scrapy </span>pymongo</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>另外这个项目依赖于 MongoDB，不过我们这里仅仅测试，可以取消它的依赖，setting.py 中注释掉如下代码：</p>
                  <figure class="highlight diff">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line">ITEM_PIPELINES = &#123;</span><br><span class="line">    'tutorial.pipelines.TextPipeline': 300,</span><br><span class="line"><span class="deletion">-    'tutorial.pipelines.MongoDBPipeline': 400,</span></span><br><span class="line"><span class="addition">+    #'tutorial.pipelines.MongoDBPipeline': 400,</span></span><br><span class="line">&#125;</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>然后接下来可以运行如下命令启动爬虫了：</p>
                  <figure class="highlight ebnf">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="attribute">scrapy crawl quotes</span></span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>这时候就可以看到爬虫就成功运行了，如图所示：</p>
                  <p><img src="https://qiniu.cuiqingcai.com/iwoga.png" alt="image-20201111015327574"></p>
                  <p>完美，Clone 的项目也成功运行了，美滋滋。</p>
                  <p>最后我们看看这个退出之后怎么样，先复制下当前的 URL，我的 URL 是 <a href="https://ide.devcloud.cn-north-4.huaweicloud.com/cce-5/sermgcaktl/#/home/user/projects/ScrapyTutorial，然后我们直接关掉当前页面选项卡，然后重新进入，看看现在的运行状态还在不在。" target="_blank" rel="noopener">https://ide.devcloud.cn-north-4.huaweicloud.com/cce-5/sermgcaktl/#/home/user/projects/ScrapyTutorial，然后我们直接关掉当前页面选项卡，然后重新进入，看看现在的运行状态还在不在。</a></p>
                  <p>牛逼！重新进入之后还是原来的样子，控制台依然还是开的，跑的结果也依然有！</p>
                  <p><img src="https://qiniu.cuiqingcai.com/bk9rc.png" alt="image-20201111015741812"></p>
                  <p>很好！</p>
                  <p>那这个环境怎么分享给别人呢？看了下「华为云CloudIDE」是支持分享功能的，这里可以进入到 CloudIDE 的首页，点击管理，然后通过白名单或者黑名单的方式添加用户就可以了。</p>
                  <p><img src="https://qiniu.cuiqingcai.com/uqi8m.png" alt="image-20201111020023870"></p>
                  <p>好了，到现在为止「华为云CloudIDE」就体验完了，感觉整体上还是挺不错的，大家也可以来体验试试看吧！</p>
                  </p>
                </div>
              </div>
              <div class="post-meta">
                <span class="post-meta-item">
                  <span class="post-meta-item-icon">
                    <i class="far fa-user"></i>
                  </span>
                  <span class="post-meta-item-text">作者</span>
                  <span><a href="/authors/崔庆才" class="author" itemprop="url" rel="index">崔庆才</a></span>
                </span>
                <span class="post-meta-item">
                  <span class="post-meta-item-icon">
                    <i class="far fa-calendar"></i>
                  </span>
                  <span class="post-meta-item-text">发表于</span>
                  <time title="创建时间：2020-11-11 01:28:24" itemprop="dateCreated datePublished" datetime="2020-11-11T01:28:24+08:00">2020-11-11</time>
                </span>
                <span id="/23855.html" class="post-meta-item leancloud_visitors" data-flag-title="华为云CloudIDE带你实现云上编码" title="阅读次数">
                  <span class="post-meta-item-icon">
                    <i class="fa fa-eye"></i>
                  </span>
                  <span class="post-meta-item-text">阅读次数：</span>
                  <span class="leancloud-visitors-count"></span>
                </span>
                <span class="post-meta-item" title="本文字数">
                  <span class="post-meta-item-icon">
                    <i class="far fa-file-word"></i>
                  </span>
                  <span class="post-meta-item-text">本文字数：</span>
                  <span>4.1k</span>
                </span>
                <span class="post-meta-item" title="阅读时长">
                  <span class="post-meta-item-icon">
                    <i class="far fa-clock"></i>
                  </span>
                  <span class="post-meta-item-text">阅读时长 &asymp;</span>
                  <span>4 分钟</span>
                </span>
              </div>
            </article>
            <article itemscope itemtype="http://schema.org/Article" class="post-block index" lang="zh-CN">
              <link itemprop="mainEntityOfPage" href="https://cuiqingcai.com/23184.html">
              <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
                <meta itemprop="image" content="/images/avatar.png">
                <meta itemprop="name" content="崔庆才">
                <meta itemprop="description" content="崔庆才的个人站点，记录生活的瞬间，分享学习的心得。">
              </span>
              <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
                <meta itemprop="name" content="静觅">
              </span>
              <header class="post-header">
                <h2 class="post-title" itemprop="name headline">
                  <a class="label"> 技术杂谈 <i class="label-arrow"></i>
                  </a>
                  <a href="/23184.html" class="post-title-link" itemprop="url">Kubectl部署筹备</a>
                </h2>
              </header>
              <div class="post-body" itemprop="articleBody">
                <div class="thumb">
                  <img itemprop="contentUrl" class="random">
                </div>
                <div class="excerpt">
                  <p>
                  <h2 id="YAML文件概述"><a href="#YAML文件概述" class="headerlink" title="YAML文件概述"></a>YAML文件概述</h2>
                  <p>K8s集群文件中对资源管理和资源对象编排部署都可以通过声明样式<code>yaml</code>,文件来解决，也就是说可以把需要对资源对象操作编辑到<code>yaml</code>,文件中。</p>
                  <p>我们称之为<code>资源清单</code>或<code>资源清单文件</code>通过kubectl命令直接使用资源清单文件就可以实现对大量资源对象进行编排部署</p>
                  <h3 id="基本语法"><a href="#基本语法" class="headerlink" title="基本语法"></a>基本语法</h3>
                  <ul>
                    <li>大小写敏感</li>
                    <li>使用缩进表示层级关系，缩进不允许使用tab，只允许空格</li>
                    <li>缩进的空格数不重要，只要相同层级的元素左对齐即可</li>
                    <li>‘#’表示注释</li>
                    <li><code>---</code>表示新的yaml文件的开始<h3 id="数据类型"><a href="#数据类型" class="headerlink" title="数据类型"></a>数据类型</h3>YAML 支持以下几种数据类型：</li>
                    <li>对象：键值对的集合，又称为映射（mapping）/ 哈希（hashes） / 字典（dictionary）</li>
                    <li>数组：一组按次序排列的值，又称为序列（sequence） / 列表（list）</li>
                    <li>纯量（scalars）：单个的、不可再分的值<h3 id="常量"><a href="#常量" class="headerlink" title="常量"></a>常量</h3>常量是最基本的，不可再分的值，包括：</li>
                    <li>字符串</li>
                    <li>布尔值</li>
                    <li>整数</li>
                    <li>浮点数</li>
                    <li>Null</li>
                    <li>时间</li>
                    <li>日期<h3 id="引用"><a href="#引用" class="headerlink" title="引用"></a>引用</h3>
                      <blockquote>
                        <p><strong>&amp;</strong> 锚点和 <strong>*</strong> 别名，可以用来引用:</p>
                        <p><strong>&amp;</strong> 用来建立锚点（defaults），<strong>&lt;&lt;</strong> 表示合并到当前数据，<strong>*</strong> 用来引用锚点。</p>
                        <figure class="highlight yaml">
                          <table>
                            <tr>
                              <td class="gutter">
                                <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre>
                              </td>
                              <td class="code">
                                <pre><span class="line"><span class="attr">defaults:</span> <span class="meta">&amp;defaults</span></span><br><span class="line">  <span class="attr">adapter:</span>  <span class="string">postgres</span></span><br><span class="line">  <span class="attr">host:</span>     <span class="string">localhost</span></span><br><span class="line"><span class="attr">development:</span></span><br><span class="line">  <span class="attr">database:</span> <span class="string">myapp_development</span></span><br><span class="line">  <span class="string">&lt;&lt;:</span> <span class="meta">*defaults</span></span><br><span class="line"><span class="attr">test:</span></span><br><span class="line">  <span class="attr">database:</span> <span class="string">myapp_test</span></span><br><span class="line">  <span class="string">&lt;&lt;:</span> <span class="meta">*defaults</span></span><br><span class="line"><span class="string">---相当于</span></span><br><span class="line"><span class="attr">defaults:</span></span><br><span class="line">  <span class="attr">adapter:</span>  <span class="string">postgres</span></span><br><span class="line">  <span class="attr">host:</span>     <span class="string">localhost</span></span><br><span class="line"><span class="attr">development:</span></span><br><span class="line">  <span class="attr">database:</span> <span class="string">myapp_development</span></span><br><span class="line">  <span class="attr">adapter:</span>  <span class="string">postgres</span></span><br><span class="line">  <span class="attr">host:</span>     <span class="string">localhost</span></span><br><span class="line"><span class="attr">test:</span></span><br><span class="line">  <span class="attr">database:</span> <span class="string">myapp_test</span></span><br><span class="line">  <span class="attr">adapter:</span>  <span class="string">postgres</span></span><br><span class="line">  <span class="attr">host:</span>     <span class="string">localhost</span></span><br></pre>
                              </td>
                            </tr>
                          </table>
                        </figure>
                        <h2 id="kubernetes中yaml组成部分"><a href="#kubernetes中yaml组成部分" class="headerlink" title="kubernetes中yaml组成部分"></a>kubernetes中yaml组成部分</h2>
                        <figure class="highlight yaml">
                          <table>
                            <tr>
                              <td class="gutter">
                                <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br></pre>
                              </td>
                              <td class="code">
                                <pre><span class="line"><span class="attr">apiVersion:</span> <span class="string">v1</span>								<span class="comment"># API版本 可使用命令kubeclt api--verison查看</span></span><br><span class="line"><span class="attr">kind:</span> <span class="string">ReplicationController</span>		<span class="comment"># 资源类型 - 副本控制器RC</span></span><br><span class="line"><span class="attr">metadata:</span>											<span class="comment"># 资源元数据</span></span><br><span class="line">  <span class="attr">name:</span> <span class="string">mysql</span>									<span class="comment"># 	- RC的名称(全局唯一)，符合目标的Pod拥有此标签</span></span><br><span class="line"><span class="attr">spec:</span>													<span class="comment"># 资源的规格(RC的相关属性的定义)</span></span><br><span class="line">  <span class="attr">replicas:</span> <span class="number">1</span>									<span class="comment"># 副本的期望数量</span></span><br><span class="line">  <span class="attr">selector:</span>										<span class="comment"># 标签选择器</span></span><br><span class="line">    <span class="attr">app:</span> <span class="string">mysql</span>				</span><br><span class="line"> <span class="comment"># *********************************************</span></span><br><span class="line">  <span class="attr">template:</span>										<span class="comment"># Pod 模版</span></span><br><span class="line">    <span class="attr">metadata:</span>						</span><br><span class="line">      <span class="attr">name:</span> <span class="string">mysql</span></span><br><span class="line">      <span class="attr">labels:</span>									<span class="comment"># 标签		Pod 副本拥有的标签，对应RC的Selector</span></span><br><span class="line">        <span class="attr">app:</span> <span class="string">mysql</span></span><br><span class="line">    <span class="attr">spec:</span>											<span class="comment"># Pod规格</span></span><br><span class="line">      <span class="attr">containers:</span>							<span class="comment"># 容器的配置</span></span><br><span class="line">        <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">mysql</span>					<span class="comment"># 容器名称</span></span><br><span class="line">          <span class="attr">image:</span> <span class="string">mysql</span>				<span class="comment"># 容器镜像(对应的Docker images)</span></span><br><span class="line">          <span class="attr">ports:</span></span><br><span class="line">            <span class="bullet">-</span> <span class="attr">containerPort:</span> <span class="number">3306</span>		<span class="comment"># 容器引用监听的端口号</span></span><br><span class="line">          <span class="attr">env:</span>											<span class="comment"># 环境配置</span></span><br><span class="line">            <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">MYSQL_ROOT_PASSWORD</span>	</span><br><span class="line">              <span class="attr">value:</span> <span class="string">"123456"</span></span><br><span class="line">              </span><br><span class="line">              </span><br><span class="line">  <span class="string">---</span></span><br><span class="line"><span class="attr">apiVersion:</span> <span class="string">v1</span></span><br><span class="line"><span class="attr">kind:</span> <span class="string">Service</span> 								<span class="comment">#  资源类型 服务</span></span><br><span class="line"><span class="attr">metadata:</span></span><br><span class="line">  <span class="attr">name:</span> <span class="string">mysql</span>			</span><br><span class="line"><span class="attr">spec:</span></span><br><span class="line">  <span class="attr">selector:</span></span><br><span class="line">    <span class="attr">app:</span> <span class="string">mysql</span></span><br><span class="line">  <span class="attr">ports:</span></span><br><span class="line">  <span class="bullet">-</span> <span class="attr">port:</span> <span class="number">3306</span></span><br></pre>
                              </td>
                            </tr>
                          </table>
                        </figure>
                      </blockquote>
                    </li>
                    <li>控制器部分<br><img src="https://tva1.sinaimg.cn/large/0081Kckwgy1gka2eynwi4j30dw07ygm8.jpg" alt="控制器部分" style="zoom:139%;" /></li>
                    <li>被控制的对象<br><img src="https://tva1.sinaimg.cn/large/0081Kckwgy1gka2i29sqpj30j80e8ta8.jpg" alt="被控制的对象"></li>
                    <li>RC<br><img src="https://tva1.sinaimg.cn/large/0081Kckwgy1gka3668adhj31ap0u0jyb.jpg" alt="RC" style="zoom:45%;" />
                      <h2 id="快速编写yaml文件"><a href="#快速编写yaml文件" class="headerlink" title="快速编写yaml文件"></a>快速编写yaml文件</h2>
                      <h3 id="Part-1-使用命令生成yaml文件"><a href="#Part-1-使用命令生成yaml文件" class="headerlink" title="Part 1:使用命令生成yaml文件"></a>Part 1:使用命令生成yaml文件</h3>
                      <figure class="highlight sh">
                        <table>
                          <tr>
                            <td class="gutter">
                              <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre>
                            </td>
                            <td class="code">
                              <pre><span class="line"><span class="comment"># kubectl create </span></span><br><span class="line">kubectl create deployment web --image=nginx -o yaml --dry-run</span><br><span class="line"><span class="comment"># -o 使用yaml格式展示</span></span><br><span class="line"><span class="comment"># -dry-run 尝试运行，并不会真正运行</span></span><br><span class="line"><span class="comment"># 保存至myweb.yaml</span></span><br><span class="line">kubectl create deployment web --image=nginx -o yaml --dry-run &gt; myweb.yaml</span><br></pre>
                            </td>
                          </tr>
                        </table>
                      </figure>
                    </li>
                    <li>kubectl create deployment web —image=nginx -o yaml —dry-run运行效果如下⬇️:<br><img src="https://tva1.sinaimg.cn/large/0081Kckwgy1gka3obd2j7j31bo0ketgm.jpg" alt="kubectl create">
                      <h3 id="Part-2-使用命令导出yaml文件"><a href="#Part-2-使用命令导出yaml文件" class="headerlink" title="Part 2: 使用命令导出yaml文件"></a>Part 2: 使用命令导出yaml文件</h3>
                      <figure class="highlight sh">
                        <table>
                          <tr>
                            <td class="gutter">
                              <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre>
                            </td>
                            <td class="code">
                              <pre><span class="line">kubectl get</span><br><span class="line">kubectl get deploy <span class="comment"># 查看部署</span></span><br><span class="line">kubectl get deploy nginx -o yaml --<span class="built_in">export</span> &gt; myweb.yaml</span><br></pre>
                            </td>
                          </tr>
                        </table>
                      </figure>
                    </li>
                  </ul>
                  <h2 id="kubectl命令学习"><a href="#kubectl命令学习" class="headerlink" title="kubectl命令学习"></a>kubectl命令学习</h2>
                  <p>这里简单记录下 Kubectl 部署的一些准备工作。</p>
                  <figure class="highlight sh">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line">Basic Commands (Beginner):</span><br><span class="line">  create         <span class="comment"># Create a resource from a file or from stdin.</span></span><br><span class="line">  expose         <span class="comment"># 使用 replication controller, service, deployment 或者 pod 并暴露它作为一个 新的</span></span><br><span class="line">Kubernetes Service</span><br><span class="line">  run            <span class="comment"># 在集群中运行一个指定的镜像</span></span><br><span class="line">  <span class="built_in">set</span>            <span class="comment"># 为 objects 设置一个指定的特征</span></span><br><span class="line"></span><br><span class="line">Basic Commands (Intermediate):</span><br><span class="line">  explain        <span class="comment"># 查看资源的文档</span></span><br><span class="line">  get            <span class="comment"># 显示一个或更多 resources</span></span><br><span class="line">  edit           <span class="comment"># 在服务器上编辑一个资源</span></span><br><span class="line">  delete         <span class="comment"># Delete resources by filenames, stdin, resources and names, or by resources and label selector</span></span><br><span class="line"></span><br><span class="line">Deploy Commands:</span><br><span class="line">  rollout        <span class="comment"># Manage the rollout of a resource</span></span><br><span class="line">  scale          <span class="comment"># 为 Deployment, ReplicaSet, Replication Controller 或者 Job 设置一个新的副本数量</span></span><br><span class="line">  autoscale      <span class="comment"># 自动调整一个 Deployment, ReplicaSet, 或者 ReplicationController 的副本数量</span></span><br><span class="line"></span><br><span class="line">Cluster Management Commands:</span><br><span class="line">  certificate    <span class="comment"># 修改 certificate 资源.</span></span><br><span class="line">  cluster-info   <span class="comment"># 显示集群信息</span></span><br><span class="line">  top            <span class="comment"># Display Resource (CPU/Memory/Storage) usage.</span></span><br><span class="line">  cordon         <span class="comment"># 标记 node 为 unschedulable</span></span><br><span class="line">  uncordon       <span class="comment"># 标记 node 为 schedulable</span></span><br><span class="line">  drain          <span class="comment"># Drain node in preparation for maintenance</span></span><br><span class="line">  taint          <span class="comment"># 更新一个或者多个 node 上的 taints</span></span><br><span class="line"></span><br><span class="line">Troubleshooting and Debugging Commands:</span><br><span class="line">  describe       <span class="comment"># 显示一个指定 resource 或者 group 的 resources 详情</span></span><br><span class="line">  logs           <span class="comment"># 输出容器在 pod 中的日志</span></span><br><span class="line">  attach         <span class="comment"># Attach 到一个运行中的 container</span></span><br><span class="line">  <span class="built_in">exec</span>           <span class="comment"># 在一个 container 中执行一个命令</span></span><br><span class="line">  port-forward   <span class="comment"># Forward one or more local ports to a pod</span></span><br><span class="line">  proxy          <span class="comment"># 运行一个 proxy 到 Kubernetes API server</span></span><br><span class="line">  cp             <span class="comment"># 复制 files 和 directories 到 containers 和从容器中复制 files 和 directories.</span></span><br><span class="line">  auth           <span class="comment"># Inspect authorization</span></span><br><span class="line"></span><br><span class="line">Advanced Commands:</span><br><span class="line">  diff           <span class="comment"># Diff live version against would-be applied version</span></span><br><span class="line">  apply          <span class="comment"># 通过文件名或标准输入流(stdin)对资源进行配置</span></span><br><span class="line">  patch          <span class="comment"># 使用 strategic merge patch 更新一个资源的 field(s)</span></span><br><span class="line">  replace        <span class="comment"># 通过 filename 或者 stdin替换一个资源</span></span><br><span class="line">  <span class="built_in">wait</span>           <span class="comment"># Experimental: Wait for a specific condition on one or many resources.</span></span><br><span class="line">  convert        <span class="comment"># 在不同的 API versions 转换配置文件</span></span><br><span class="line">  kustomize      <span class="comment"># Build a kustomization target from a directory or a remote url.</span></span><br><span class="line"></span><br><span class="line">Settings Commands:</span><br><span class="line">  label          <span class="comment"># 更新在这个资源上的 labels</span></span><br><span class="line">  annotate       <span class="comment"># 更新一个资源的注解</span></span><br><span class="line">  completion     <span class="comment"># Output shell completion code for the specified shell (bash or zsh)</span></span><br><span class="line"></span><br><span class="line">Other Commands:</span><br><span class="line">  api-resources  <span class="comment"># Print the supported API resources on the server</span></span><br><span class="line">  api-versions   <span class="comment"># Print the supported API versions on the server, in the form of "group/version"</span></span><br><span class="line">  config         <span class="comment"># 修改 kubeconfig 文件</span></span><br><span class="line">  plugin         <span class="comment"># Provides utilities for interacting with plugins.</span></span><br><span class="line">  version        <span class="comment"># 输出 client 和 server 的版本信息</span></span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <h2 id="Kubectl-create"><a href="#Kubectl-create" class="headerlink" title="Kubectl create"></a>Kubectl create</h2>
                  <figure class="highlight sh">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line">Create a resource from a file or from stdin.</span><br><span class="line"></span><br><span class="line"> JSON and YAML formats are accepted.</span><br><span class="line"></span><br><span class="line">Examples:</span><br><span class="line">  <span class="comment"># Create a pod using the data in pod.json.</span></span><br><span class="line">  kubectl create -f ./pod.json</span><br><span class="line">  </span><br><span class="line">  <span class="comment"># Create a pod based on the JSON passed into stdin.</span></span><br><span class="line">  cat pod.json | kubectl create -f -</span><br><span class="line">  </span><br><span class="line">  <span class="comment"># Edit the data in docker-registry.yaml in JSON then create the resource using the edited data.</span></span><br><span class="line">  kubectl create -f docker-registry.yaml --edit -o json</span><br><span class="line"></span><br><span class="line">Available Commands:</span><br><span class="line">  clusterrole         <span class="comment"># Create a ClusterRole.</span></span><br><span class="line">  clusterrolebinding  <span class="comment"># 为一个指定的 ClusterRole 创建一个 ClusterRoleBinding</span></span><br><span class="line">  configmap           <span class="comment"># 从本地 file, directory 或者 literal value 创建一个 configmap</span></span><br><span class="line">  cronjob             <span class="comment"># Create a cronjob with the specified name.</span></span><br><span class="line">  deployment          <span class="comment"># 创建一个指定名称的 deployment.</span></span><br><span class="line">  job                 <span class="comment"># Create a job with the specified name.</span></span><br><span class="line">  namespace           <span class="comment"># 创建一个指定名称的 namespace</span></span><br><span class="line">  poddisruptionbudget <span class="comment"># 创建一个指定名称的 pod disruption budget.</span></span><br><span class="line">  priorityclass       <span class="comment"># Create a priorityclass with the specified name.</span></span><br><span class="line">  quota               <span class="comment"># 创建一个指定名称的 quota.</span></span><br><span class="line">  role                <span class="comment"># Create a role with single rule.</span></span><br><span class="line">  rolebinding         <span class="comment"># 为一个指定的 Role 或者 ClusterRole创建一个 RoleBinding</span></span><br><span class="line">  secret              <span class="comment"># 使用指定的 subcommand 创建一个 secret</span></span><br><span class="line">  service             <span class="comment"># 使用指定的 subcommand 创建一个 service.</span></span><br><span class="line">  serviceaccount      <span class="comment"># 创建一个指定名称的 service account</span></span><br><span class="line"></span><br><span class="line">Options:</span><br><span class="line">      --allow-missing-template-keys=<span class="literal">true</span>: If <span class="literal">true</span>, ignore any errors <span class="keyword">in</span> templates when a field or map key is missing <span class="keyword">in</span> the template. Only applies to golang and jsonpath output formats.</span><br><span class="line">      --dry-run=<span class="literal">false</span>: If <span class="literal">true</span>, only <span class="built_in">print</span> the object that would be sent, without sending it.</span><br><span class="line">      --edit=<span class="literal">false</span>: Edit the API resource before creating</span><br><span class="line">  -f, --filename=[]: Filename, directory, or URL to files to use to create the resource</span><br><span class="line">  -k, --kustomize=<span class="string">''</span>: Process the kustomization directory. This flag can<span class="string">'t be used together with -f or -R.</span></span><br><span class="line"><span class="string">  -o, --output='</span><span class="string">': Output format. One of:</span></span><br><span class="line"><span class="string">json|yaml|name|go-template|go-template-file|template|templatefile|jsonpath|jsonpath-file.</span></span><br><span class="line"><span class="string">      --raw='</span><span class="string">': Raw URI to POST to the server.  Uses the transport specified by the kubeconfig file.</span></span><br><span class="line"><span class="string">      --record=false: Record current kubectl command in the resource annotation. If set to false, do not record the</span></span><br><span class="line"><span class="string">command. If set to true, record the command. If not set, default to updating the existing annotation value only if one</span></span><br><span class="line"><span class="string">already exists.</span></span><br><span class="line"><span class="string">  -R, --recursive=false: Process the directory used in -f, --filename recursively. Useful when you want to manage</span></span><br><span class="line"><span class="string">related manifests organized within the same directory.</span></span><br><span class="line"><span class="string">      --save-config=false: If true, the configuration of current object will be saved in its annotation. Otherwise, the</span></span><br><span class="line"><span class="string">annotation will be unchanged. This flag is useful when you want to perform kubectl apply on this object in the future.</span></span><br><span class="line"><span class="string">  -l, --selector='</span><span class="string">': Selector (label query) to filter on, supports '</span>=<span class="string">', '</span>==<span class="string">', and '</span>!=<span class="string">'.(e.g. -l key1=value1,key2=value2)</span></span><br><span class="line"><span class="string">      --template='</span><span class="string">': Template string or path to template file to use when -o=go-template, -o=go-template-file. The</span></span><br><span class="line"><span class="string">template format is golang templates [http://golang.org/pkg/text/template/#pkg-overview].</span></span><br><span class="line"><span class="string">      --validate=true: If true, use a schema to validate the input before sending it</span></span><br><span class="line"><span class="string">      --windows-line-endings=false: Only relevant if --edit=true. Defaults to the line ending native to your platform.</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">Usage:</span></span><br><span class="line"><span class="string">  kubectl create -f FILENAME [options]</span></span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  </p>
                </div>
              </div>
              <div class="post-meta">
                <span class="post-meta-item">
                  <span class="post-meta-item-icon">
                    <i class="far fa-user"></i>
                  </span>
                  <span class="post-meta-item-text">作者</span>
                  <span><a href="/authors/Payne" class="author" itemprop="url" rel="index">Payne</a></span>
                </span>
                <span class="post-meta-item">
                  <span class="post-meta-item-icon">
                    <i class="far fa-calendar"></i>
                  </span>
                  <span class="post-meta-item-text">发表于</span>
                  <time title="创建时间：2020-11-02 01:28:24" itemprop="dateCreated datePublished" datetime="2020-11-02T01:28:24+08:00">2020-11-02</time>
                </span>
                <span id="/23184.html" class="post-meta-item leancloud_visitors" data-flag-title="Kubectl部署筹备" title="阅读次数">
                  <span class="post-meta-item-icon">
                    <i class="fa fa-eye"></i>
                  </span>
                  <span class="post-meta-item-text">阅读次数：</span>
                  <span class="leancloud-visitors-count"></span>
                </span>
                <span class="post-meta-item" title="本文字数">
                  <span class="post-meta-item-icon">
                    <i class="far fa-file-word"></i>
                  </span>
                  <span class="post-meta-item-text">本文字数：</span>
                  <span>6.5k</span>
                </span>
                <span class="post-meta-item" title="阅读时长">
                  <span class="post-meta-item-icon">
                    <i class="far fa-clock"></i>
                  </span>
                  <span class="post-meta-item-text">阅读时长 &asymp;</span>
                  <span>6 分钟</span>
                </span>
              </div>
            </article>
            <article itemscope itemtype="http://schema.org/Article" class="post-block index" lang="zh-CN">
              <link itemprop="mainEntityOfPage" href="https://cuiqingcai.com/23854.html">
              <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
                <meta itemprop="image" content="/images/avatar.png">
                <meta itemprop="name" content="崔庆才">
                <meta itemprop="description" content="崔庆才的个人站点，记录生活的瞬间，分享学习的心得。">
              </span>
              <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
                <meta itemprop="name" content="静觅">
              </span>
              <header class="post-header">
                <h2 class="post-title" itemprop="name headline">
                  <a class="label"> 技术杂谈 <i class="label-arrow"></i>
                  </a>
                  <a href="/23854.html" class="post-title-link" itemprop="url">Hexo构建时内存溢出 FatalProcessOutOfMemory 解决方案</a>
                </h2>
              </header>
              <div class="post-body" itemprop="articleBody">
                <div class="thumb">
                  <img itemprop="contentUrl" class="random">
                </div>
                <div class="excerpt">
                  <p>
                  <p>最近博客换上了 Hexo，但是发现经常莫名其妙构建失败，报内存溢出，Out of Memory，错误如下：</p>
                  <figure class="highlight angelscript">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line">==== JS stack trace =========================================</span><br><span class="line"></span><br><span class="line">    <span class="number">0</span>: ExitFrame [pc: <span class="number">0x1409219</span>]</span><br><span class="line">Security context: <span class="number">0x36ffd21408d1</span> &lt;JSObject&gt;</span><br><span class="line">    <span class="number">1</span>: <span class="keyword">get</span> sticky [<span class="number">0x36ffd2149801</span>](<span class="keyword">this</span>=<span class="number">0x1e69c6f730e1</span> &lt;JSRegExp &lt;String[<span class="number">10</span>]: [\t \n\r]+&gt;&gt;)</span><br><span class="line">    <span class="number">2</span>: match [<span class="number">0x6ca6396ae39</span>] [/github/workspace/node_modules/js-beautify/js/src/core/inputscanner.js:~<span class="number">110</span>] [pc=<span class="number">0x1d19a16be4dc</span>](<span class="keyword">this</span>=<span class="number">0x1e69c6f73119</span> &lt;InputScanner map = <span class="number">0x1c206a47a549</span>&gt;,<span class="number">0x1e69c6f730e1</span> &lt;JSRegExp &lt;String[<span class="number">10</span>]: [\t \n\r]+&gt;&gt;)</span><br><span class="line">    <span class="number">3</span>: tokenize [<span class="number">0x6ca6396e171</span>] [/gith...</span><br><span class="line"></span><br><span class="line"> <span class="number">1</span>: <span class="number">0xa17c40</span> node::Abort() [hexo]</span><br><span class="line"> <span class="number">2</span>: <span class="number">0xa1804c</span> node::OnFatalError(char <span class="keyword">const</span>*, char <span class="keyword">const</span>*) [hexo]</span><br><span class="line"> <span class="number">3</span>: <span class="number">0xb95a7e</span> v8::Utils::ReportOOMFailure(v8::<span class="built_in">int</span>ernal::Isolate*, char <span class="keyword">const</span>*, <span class="built_in">bool</span>) [hexo]</span><br><span class="line"> <span class="number">4</span>: <span class="number">0xb95df9</span> v8::<span class="built_in">int</span>ernal::V8::FatalProcessOutOfMemory(v8::<span class="built_in">int</span>ernal::Isolate*, char <span class="keyword">const</span>*, <span class="built_in">bool</span>) [hexo]</span><br><span class="line"> <span class="number">5</span>: <span class="number">0xd53075</span>  [hexo]</span><br><span class="line"> <span class="number">6</span>: <span class="number">0xd53706</span> v8::<span class="built_in">int</span>ernal::Heap::RecomputeLimits(v8::<span class="built_in">int</span>ernal::GarbageCollector) [hexo]</span><br><span class="line"> <span class="number">7</span>: <span class="number">0xd5ffc5</span> v8::<span class="built_in">int</span>ernal::Heap::PerformGarbageCollection(v8::<span class="built_in">int</span>ernal::GarbageCollector, v8::GCCallbackFlags) [hexo]</span><br><span class="line"> <span class="number">8</span>: <span class="number">0xd60e75</span> v8::<span class="built_in">int</span>ernal::Heap::CollectGarbage(v8::<span class="built_in">int</span>ernal::AllocationSpace, v8::<span class="built_in">int</span>ernal::GarbageCollectionReason, v8::GCCallbackFlags) [hexo]</span><br><span class="line"> <span class="number">9</span>: <span class="number">0xd6251f</span> v8::<span class="built_in">int</span>ernal::Heap::HandleGCRequest() [hexo]</span><br><span class="line"><span class="number">10</span>: <span class="number">0xd10f85</span> v8::<span class="built_in">int</span>ernal::StackGuard::HandleInterrupts() [hexo]</span><br><span class="line"><span class="number">11</span>: <span class="number">0x106c5c6</span> v8::<span class="built_in">int</span>ernal::Runtime_StackGuard(<span class="built_in">int</span>, unsigned long*, v8::<span class="built_in">int</span>ernal::Isolate*) [hexo]</span><br><span class="line"><span class="number">12</span>: <span class="number">0x1409219</span>  [hexo]</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>原因就是内存溢出了，这是因为 Hexo 在构建的时候存了一个特别大的数组，而默认 Node 运行时最大内存为 512 MB，详情可以见：<a href="https://github.com/hexojs/hexo/issues/2165。" target="_blank" rel="noopener">https://github.com/hexojs/hexo/issues/2165。</a></p>
                  <p>真是服了，才几百篇文章就不行了，耗费内存至于这么多吗？</p>
                  <p>解决方案，可以直接设置 Node 的最大内存限制，比如我直接设置为 16G，在构建之前执行如下命令就行了：</p>
                  <figure class="highlight routeros">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="builtin-name">export</span> <span class="attribute">NODE_OPTIONS</span>=<span class="string">"--max-old-space-size=16384"</span></span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>这样就设置了 Node 运行时的最大内存，就不会触发内存溢出了。</p>
                  </p>
                </div>
              </div>
              <div class="post-meta">
                <span class="post-meta-item">
                  <span class="post-meta-item-icon">
                    <i class="far fa-user"></i>
                  </span>
                  <span class="post-meta-item-text">作者</span>
                  <span><a href="/authors/崔庆才" class="author" itemprop="url" rel="index">崔庆才</a></span>
                </span>
                <span class="post-meta-item">
                  <span class="post-meta-item-icon">
                    <i class="far fa-calendar"></i>
                  </span>
                  <span class="post-meta-item-text">发表于</span>
                  <time title="创建时间：2020-11-01 01:37:43" itemprop="dateCreated datePublished" datetime="2020-11-01T01:37:43+08:00">2020-11-01</time>
                </span>
                <span id="/23854.html" class="post-meta-item leancloud_visitors" data-flag-title="Hexo构建时内存溢出 FatalProcessOutOfMemory 解决方案" title="阅读次数">
                  <span class="post-meta-item-icon">
                    <i class="fa fa-eye"></i>
                  </span>
                  <span class="post-meta-item-text">阅读次数：</span>
                  <span class="leancloud-visitors-count"></span>
                </span>
                <span class="post-meta-item" title="本文字数">
                  <span class="post-meta-item-icon">
                    <i class="far fa-file-word"></i>
                  </span>
                  <span class="post-meta-item-text">本文字数：</span>
                  <span>1.7k</span>
                </span>
                <span class="post-meta-item" title="阅读时长">
                  <span class="post-meta-item-icon">
                    <i class="far fa-clock"></i>
                  </span>
                  <span class="post-meta-item-text">阅读时长 &asymp;</span>
                  <span>2 分钟</span>
                </span>
              </div>
            </article>
            <article itemscope itemtype="http://schema.org/Article" class="post-block index" lang="zh-CN">
              <link itemprop="mainEntityOfPage" href="https://cuiqingcai.com/23853.html">
              <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
                <meta itemprop="image" content="/images/avatar.png">
                <meta itemprop="name" content="崔庆才">
                <meta itemprop="description" content="崔庆才的个人站点，记录生活的瞬间，分享学习的心得。">
              </span>
              <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
                <meta itemprop="name" content="静觅">
              </span>
              <header class="post-header">
                <h2 class="post-title" itemprop="name headline">
                  <a class="label"> Markdown <i class="label-arrow"></i>
                  </a>
                  <a href="/23853.html" class="post-title-link" itemprop="url">Markdown如何实现代码增删对比效果</a>
                </h2>
              </header>
              <div class="post-body" itemprop="articleBody">
                <div class="thumb">
                  <img itemprop="contentUrl" class="random">
                </div>
                <div class="excerpt">
                  <p>
                  <p>在写文章的时候我经常会遇到这么一个需求，我想要跟大家说明某一行代码需要改动成另外一行代码。</p>
                  <p>比如我这里有一段代码：</p>
                  <figure class="highlight dockerfile">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="keyword">FROM</span> python:<span class="number">3.6</span></span><br><span class="line"><span class="keyword">WORKDIR</span><span class="bash"> /app</span></span><br><span class="line"><span class="keyword">COPY</span><span class="bash"> . .</span></span><br><span class="line"><span class="keyword">RUN</span><span class="bash"> pip install -r requirements.txt</span></span><br><span class="line"><span class="keyword">VOLUME</span><span class="bash"> [<span class="string">"/app/proxypool/crawlers/private"</span>]</span></span><br><span class="line"><span class="keyword">CMD</span><span class="bash"> [<span class="string">"supervisord"</span>, <span class="string">"-c"</span>, <span class="string">"supervisord.conf"</span>]</span></span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>仅仅作为示例，这里行号我也没标，行数也有可能很多行，比如上百行。</p>
                  <p>比如我就想告诉大家，我想把：</p>
                  <figure class="highlight dockerfile">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="keyword">RUN</span><span class="bash"> pip install -r requirements.txt</span></span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>改成：</p>
                  <figure class="highlight stylus">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line">RUN pip install -r requirements<span class="selector-class">.txt</span> -<span class="selector-tag">i</span> https:<span class="comment">//pypi.douban.com/simple</span></span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>这一行。</p>
                  <p>看，我已经说完了。</p>
                  <p>为了说这件事，我需要打好几行字，我得把原来的代码打上，然后说「改成」，然后再把新代码打上。</p>
                  <p>麻烦吧？</p>
                  <p>有没有什么更好的表述方式呢？</p>
                  <p>有。</p>
                  <p>看这里：</p>
                  <figure class="highlight diff">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="deletion">-RUN pip install -r requirements.txt</span></span><br><span class="line"><span class="addition">+RUN pip install -r requirements.txt -i https://pypi.douban.com/simple</span></span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>是不是很直观？</p>
                  <p>红色代表删减，绿色代表增加。</p>
                  <p>经常 Code Review 的朋友一定倍感亲切。</p>
                  <p>那这个怎么实现的呢？其实这就是用了 Markdown 高亮的一种写法，只需要把语言改成 diff 就好了。</p>
                  <p>原语言如下：</p>
                  <p><img src="https://qiniu.cuiqingcai.com/tpmmx.png" alt=""></p>
                  <p>这里为了防止 Markdown 解析冲突，我就用图片了。</p>
                  <p>反正就是语言标注改成 diff，然后需要删除的前面加个减号，需要增加的加个加号就行了。</p>
                  <p>完毕！</p>
                  <p>希望有帮助！</p>
                  </p>
                </div>
              </div>
              <div class="post-meta">
                <span class="post-meta-item">
                  <span class="post-meta-item-icon">
                    <i class="far fa-user"></i>
                  </span>
                  <span class="post-meta-item-text">作者</span>
                  <span><a href="/authors/崔庆才" class="author" itemprop="url" rel="index">崔庆才</a></span>
                </span>
                <span class="post-meta-item">
                  <span class="post-meta-item-icon">
                    <i class="far fa-calendar"></i>
                  </span>
                  <span class="post-meta-item-text">发表于</span>
                  <time title="创建时间：2020-11-01 00:05:48" itemprop="dateCreated datePublished" datetime="2020-11-01T00:05:48+08:00">2020-11-01</time>
                </span>
                <span id="/23853.html" class="post-meta-item leancloud_visitors" data-flag-title="Markdown如何实现代码增删对比效果" title="阅读次数">
                  <span class="post-meta-item-icon">
                    <i class="fa fa-eye"></i>
                  </span>
                  <span class="post-meta-item-text">阅读次数：</span>
                  <span class="leancloud-visitors-count"></span>
                </span>
                <span class="post-meta-item" title="本文字数">
                  <span class="post-meta-item-icon">
                    <i class="far fa-file-word"></i>
                  </span>
                  <span class="post-meta-item-text">本文字数：</span>
                  <span>707</span>
                </span>
                <span class="post-meta-item" title="阅读时长">
                  <span class="post-meta-item-icon">
                    <i class="far fa-clock"></i>
                  </span>
                  <span class="post-meta-item-text">阅读时长 &asymp;</span>
                  <span>1 分钟</span>
                </span>
              </div>
            </article>
            <article itemscope itemtype="http://schema.org/Article" class="post-block index" lang="zh-CN">
              <link itemprop="mainEntityOfPage" href="https://cuiqingcai.com/23186.html">
              <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
                <meta itemprop="image" content="/images/avatar.png">
                <meta itemprop="name" content="崔庆才">
                <meta itemprop="description" content="崔庆才的个人站点，记录生活的瞬间，分享学习的心得。">
              </span>
              <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
                <meta itemprop="name" content="静觅">
              </span>
              <header class="post-header">
                <h2 class="post-title" itemprop="name headline">
                  <a class="label"> 技术杂谈 <i class="label-arrow"></i>
                  </a>
                  <a href="/23186.html" class="post-title-link" itemprop="url">详解K8s安装及陷阱</a>
                </h2>
              </header>
              <div class="post-body" itemprop="articleBody">
                <div class="thumb">
                  <img itemprop="contentUrl" class="random">
                </div>
                <div class="excerpt">
                  <p>
                  <h1 id="kubernetes-install"><a href="#kubernetes-install" class="headerlink" title="kubernetes-install"></a>kubernetes-install</h1>
                  <h2 id="操作系统初始化"><a href="#操作系统初始化" class="headerlink" title="操作系统初始化"></a>操作系统初始化</h2>
                  <ul>
                    <li>关闭防火墙(<code>all</code>)</li>
                  </ul>
                  <figure class="highlight sh">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="comment"># 临时关闭防火墙</span></span><br><span class="line">systemctl stop firewalld</span><br><span class="line"><span class="comment"># 永久关闭防火墙</span></span><br><span class="line">systemctl <span class="built_in">disable</span> firewalld</span><br><span class="line"><span class="comment"># 验证 </span></span><br><span class="line">systemctl status firewalld</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <ul>
                    <li>关闭selinux(<code>all</code>)</li>
                  </ul>
                  <figure class="highlight sh">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="comment"># 临时关闭</span></span><br><span class="line">setenforce 0</span><br><span class="line"><span class="comment"># 永久</span></span><br><span class="line">sed -i <span class="string">'s/enforcing/disabled/'</span> /etc/selinux/config</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <ul>
                    <li>关闭swap(<code>all</code>)</li>
                  </ul>
                  <figure class="highlight sh">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="comment"># 临时</span></span><br><span class="line"> swapoff -a </span><br><span class="line"><span class="comment"># 永久</span></span><br><span class="line">sed  -ri <span class="string">'s/.*swap.*/#&amp;/'</span> /etc/fstab</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <ul>
                    <li>设置主机名称(<code>all</code>)</li>
                  </ul>
                  <figure class="highlight sh">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="comment"># 设置名称(k8s-m-1)忽略大写字母</span></span><br><span class="line">hostnamectl <span class="built_in">set</span>-hostname k8s-m-1</span><br><span class="line"><span class="comment"># 验证</span></span><br><span class="line">hostname</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <ul>
                    <li>在<code>Master</code>添加Hostname(<code>master</code>)</li>
                  </ul>
                  <figure class="highlight sh">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="comment"># 设置</span></span><br><span class="line">cat &gt;&gt; /etc/hosts &lt;&lt; EOF</span><br><span class="line">masterIp master</span><br><span class="line">node1Ip node1</span><br><span class="line">node2Ip node2</span><br><span class="line">EOF</span><br><span class="line"><span class="comment"># eg</span></span><br><span class="line">cat &gt;&gt; /etc/hosts &lt;&lt; EOF</span><br><span class="line">192.168.50.212 k8s-m-1</span><br><span class="line">192.168.50.87 k8s-n-1</span><br><span class="line">192.168.50.85 k8s-n-2</span><br><span class="line">EOF</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <ul>
                    <li>将桥接的IPV4 流量传递到iptables的链(<code>all</code>)</li>
                  </ul>
                  <figure class="highlight sh">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line">cat &gt; /etc/sysctl.d/k8s.conf &lt;&lt; EOF</span><br><span class="line">net.bridge.bridge-nf-call-ip6tables = 1</span><br><span class="line">net.bridge.bridge-nf-call-ip6tables = 1</span><br><span class="line">EOF</span><br><span class="line"><span class="comment"># 生效</span></span><br><span class="line">sysctl --system</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <ul>
                    <li>时间同步(<code>All</code>)</li>
                  </ul>
                  <figure class="highlight sh">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line">yum install -y ntpdate </span><br><span class="line">ntpdate time.windows.com</span><br><span class="line"><span class="comment"># 三台机子输出如下则成功（相差几秒或几分为正常现象）</span></span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p><img src="https://tva1.sinaimg.cn/large/0081Kckwgy1gk829whexij31bo03awgc.jpg" alt=""></p>
                  <h2 id="安装Docker"><a href="#安装Docker" class="headerlink" title="安装Docker"></a>安装Docker</h2>
                  <p><a href="https://docs.docker.com/engine/install/" target="_blank" rel="noopener">官方文档-安装</a></p>
                  <ul>
                    <li>Docker安装sh Script:(<code>All</code>)</li>
                  </ul>
                  <figure class="highlight sh">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="comment"># You can use scripts for one click installation，You may need to type enter at the end</span></span><br><span class="line"><span class="comment"># remove docker </span></span><br><span class="line">sudo yum remove docker \</span><br><span class="line">                  docker-client \</span><br><span class="line">                  docker-client-latest \</span><br><span class="line">                  docker-common \</span><br><span class="line">                  docker-latest \</span><br><span class="line">                  docker-latest-logrotate \</span><br><span class="line">                  docker-logrotate \</span><br><span class="line">                  docker-engine</span><br><span class="line"><span class="comment"># Set up repository</span></span><br><span class="line">sudo yum install -y yum-utils</span><br><span class="line"><span class="comment"># Use Aliyun Docker</span></span><br><span class="line">sudo yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo</span><br><span class="line"><span class="comment"># install docker from yum</span></span><br><span class="line">yum install  -y docker-ce docker-ce-cli containerd.io</span><br><span class="line"><span class="comment"># restart docker</span></span><br><span class="line">systemctl restart docker</span><br><span class="line"><span class="comment"># cat version </span></span><br><span class="line">docker --version</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p><img src="https://tva1.sinaimg.cn/large/0081Kckwgy1gk826sq9qgj30pg032q44.jpg" alt=""></p>
                  <ul>
                    <li>配置加速(<code>all</code>)</li>
                  </ul>
                  <figure class="highlight sh">
                    <figcaption><span>j</span></figcaption>
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line">sudo mkdir -p /etc/docker</span><br><span class="line">sudo tee /etc/docker/daemon.json &lt;&lt;-<span class="string">'EOF'</span></span><br><span class="line">&#123;</span><br><span class="line">  <span class="string">"registry-mirrors"</span>: [<span class="string">"https://etdea28s.mirror.aliyuncs.com"</span>]</span><br><span class="line">&#125;</span><br><span class="line">EOF</span><br><span class="line"></span><br><span class="line"><span class="comment"># reload</span></span><br><span class="line">sudo systemctl daemon-reload</span><br><span class="line">sudo systemctl restart docker</span><br><span class="line"></span><br><span class="line"><span class="comment"># 检查阿里云加速</span></span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p><img src="https://tva1.sinaimg.cn/large/0081Kckwgy1gk827vux9xj30p6074tb1.jpg" alt=""></p>
                  <h2 id="kubernetes安装"><a href="#kubernetes安装" class="headerlink" title="kubernetes安装"></a>kubernetes安装</h2>
                  <ul>
                    <li>配置kubernetes源(<code>all</code>)</li>
                  </ul>
                  <figure class="highlight sh">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line">cat &lt;&lt;EOF &gt; /etc/yum.repos.d/kubernetes.repo</span><br><span class="line">[kubernetes]</span><br><span class="line">name=Kubernetes</span><br><span class="line">baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/</span><br><span class="line">enabled=1</span><br><span class="line">gpgcheck=1</span><br><span class="line">repo_gpgcheck=1</span><br><span class="line">gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg</span><br><span class="line">EOF</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>由于官网kubernetes源在国外有墙，直接使用官方源会导致安装失败。所以我们配置国内的阿里源</p>
                  <ul>
                    <li>安装 kubectl kubelet kubeadm(<code>all</code>)</li>
                  </ul>
                  <figure class="highlight sh">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="comment"># install kubectl kubelet kubeadm</span></span><br><span class="line">yum install -y kubectl kubelet kubeadm</span><br><span class="line"><span class="comment"># set boot on opening computer</span></span><br><span class="line">systemctl <span class="built_in">enable</span> kubelet</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <ul>
                    <li>初始化k8s部署(<code>Master</code>)</li>
                  </ul>
                  <figure class="highlight sh">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line">kubeadm init \</span><br><span class="line">--apiserver-advertise-address=youselfIp of Master   \</span><br><span class="line">--image-repository registry.aliyuncs.com/google_containers  \</span><br><span class="line"><span class="comment"># 不冲突即可</span></span><br><span class="line">--service-cidr=10.10.0.0/16 \</span><br><span class="line">--pod-network-cidr=10.122.0.0/16</span><br><span class="line"></span><br><span class="line"><span class="comment"># eg  </span></span><br><span class="line">kubeadm init \</span><br><span class="line">--apiserver-advertise-address=192.168.50.212   \</span><br><span class="line">--image-repository registry.aliyuncs.com/google_containers  \</span><br><span class="line">--service-cidr=10.10.0.0/16 \</span><br><span class="line">--pod-network-cidr=10.122.0.0/16</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <blockquote>
                    <p>常见错误：running with swap on is not supported. Please disable swap</p>
                    <p>[preflight] If you know what you are doing, you can make a check non-fatal with `—ignore-preflight-</p>
                    <p>errors=…`</p>
                    <p>原因：系统自动进行分区</p>
                    <p>解决：</p>
                    <figure class="highlight sh">
                      <table>
                        <tr>
                          <td class="gutter">
                            <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre>
                          </td>
                          <td class="code">
                            <pre><span class="line"><span class="comment"># 临时</span></span><br><span class="line"> swapoff -a </span><br><span class="line"><span class="comment"># 永久</span></span><br><span class="line">sed  -ri <span class="string">'s/.*swap.*/#&amp;/'</span> /etc/fstab</span><br></pre>
                          </td>
                        </tr>
                      </table>
                    </figure>
                  </blockquote>
                  <ul>
                    <li>following as a regular user(<code>Master</code>)</li>
                  </ul>
                  <figure class="highlight sh">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line">mkdir -p <span class="variable">$HOME</span>/.kube</span><br><span class="line">sudo cp -i /etc/kubernetes/admin.conf <span class="variable">$HOME</span>/.kube/config</span><br><span class="line">sudo chown $(id -u):$(id -g) <span class="variable">$HOME</span>/.kube/config</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <ul>
                    <li>join master node(<code>node</code>)</li>
                  </ul>
                  <figure class="highlight angelscript">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line">kubeadm join <span class="number">172.16</span><span class="number">.164</span><span class="number">.136</span>:<span class="number">6443</span> --token <span class="number">9</span>oilao.bpbxcm5zkk0jjcgm --discovery-token-ca-cert-hash sha256:<span class="number">609794</span>bd03915be382bdb130c4c180e89cdc863d35cf99be79cf4ddcbfacee24</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>加入成功，如下图</p>
                  <p><img src="https://tva1.sinaimg.cn/large/0081Kckwgy1gk824r9yd8j31k40qmnga.jpg" alt=""></p>
                  <blockquote>
                    <p>此时我们在<code>Master</code>节点上使用命令<code>kubectl get nodes</code>查看节点信息：如下图所示</p>
                    <p><img src="https://tva1.sinaimg.cn/large/0081Kckwgy1gk82g07ydxj30p205ogod.jpg" alt=""></p>
                  </blockquote>
                  <p>此时的<code>kubectl get nodes</code>的status都是NotNotReady：</p>
                  <blockquote>
                    <p>查看kubernetes运行状态：</p>
                    <p><code>kubectl get pods -n kube-system</code></p>
                    <p>如图：</p>
                    <p><img src="https://tva1.sinaimg.cn/large/0081Kckwgy1gk82oxurldj311s0cqwm1.jpg" alt=""></p>
                    <p>果然，两个Pending犹豫未决</p>
                  </blockquote>
                  <p>此时我们部署CNI网络，配置如下</p>
                  <figure class="highlight sh">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="comment"># 根据官方文档提示配置CNI网络</span></span><br><span class="line">kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml</span><br><span class="line"><span class="comment"># 报错：The connection to the server raw.githubusercontent.com was refused - did you specify the right host or port? 原因：外网不可访问 -&gt; 在https://www.ipaddress.com/查询raw.githubusercontent.com的真实IP。</span></span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <figure class="highlight sh">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line">sudo vi /etc/hosts</span><br><span class="line">199.232.28.133 raw.githubusercontent.com</span><br><span class="line"><span class="comment"># 如下</span></span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p><img src="https://tva1.sinaimg.cn/large/0081Kckwgy1gk82x5xdgwj31b2078djr.jpg" alt=""></p>
                  <figure class="highlight sh">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="comment"># 开启IPVS，修改ConfigMap的kube-system/kube-proxy中的模式为ipvs</span></span><br><span class="line"></span><br><span class="line">kubectl edit cm kube-proxy -n kube-system </span><br><span class="line"><span class="comment"># 将空的data -&gt; ipvs -&gt; mode中替换如下</span></span><br><span class="line">mode: <span class="string">"ipvs"</span></span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p><img src="https://tva1.sinaimg.cn/large/0081Kckwgy1gk82xypglpj30rg0eo431.jpg" alt=""></p>
                  <p>在此运行<code>kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml</code>成功,如图</p>
                  <p><img src="https://tva1.sinaimg.cn/large/0081Kckwgy1gk82zbkqlej31jq08sn3c.jpg" alt=""></p>
                  <p>此时运行<code>kubectl get nodes</code>效果图如下-&gt;成功。（肯能并不一定会立马成功，上面👆确定没问题，请稍等片刻即可）</p>
                  <p><img src="https://tva1.sinaimg.cn/large/0081Kckwgy1gk831cnz4nj30p2064acr.jpg" alt=""></p>
                  <h2 id="测试kubernetes"><a href="#测试kubernetes" class="headerlink" title="测试kubernetes"></a>测试kubernetes</h2>
                  <figure class="highlight sh">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="comment"># 创建nginx镜像 Create a deployment with the specified name</span></span><br><span class="line"><span class="comment"># kubectl create deployment NAME --image=image -- [COMMAND] [args...] [options]</span></span><br><span class="line">kubectl create deployment nginx --image=nginx</span><br><span class="line"><span class="comment"># 对外暴露端口</span></span><br><span class="line">kubectl expose deployment nginx --port=80 --<span class="built_in">type</span>=NodePort</span><br><span class="line"><span class="comment"># 查看pod服务</span></span><br><span class="line">kubectl get pod,svc</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>成功</p>
                  <p><img src="https://tva1.sinaimg.cn/large/0081Kckwgy1gk83ujg3d0j31oc0latef.jpg" alt=""></p>
                  </p>
                </div>
              </div>
              <div class="post-meta">
                <span class="post-meta-item">
                  <span class="post-meta-item-icon">
                    <i class="far fa-user"></i>
                  </span>
                  <span class="post-meta-item-text">作者</span>
                  <span><a href="/authors/Payne" class="author" itemprop="url" rel="index">Payne</a></span>
                </span>
                <span class="post-meta-item">
                  <span class="post-meta-item-icon">
                    <i class="far fa-calendar"></i>
                  </span>
                  <span class="post-meta-item-text">发表于</span>
                  <time title="创建时间：2020-10-31 11:03:53" itemprop="dateCreated datePublished" datetime="2020-10-31T11:03:53+08:00">2020-10-31</time>
                </span>
                <span id="/23186.html" class="post-meta-item leancloud_visitors" data-flag-title="详解K8s安装及陷阱" title="阅读次数">
                  <span class="post-meta-item-icon">
                    <i class="fa fa-eye"></i>
                  </span>
                  <span class="post-meta-item-text">阅读次数：</span>
                  <span class="leancloud-visitors-count"></span>
                </span>
                <span class="post-meta-item" title="本文字数">
                  <span class="post-meta-item-icon">
                    <i class="far fa-file-word"></i>
                  </span>
                  <span class="post-meta-item-text">本文字数：</span>
                  <span>4.2k</span>
                </span>
                <span class="post-meta-item" title="阅读时长">
                  <span class="post-meta-item-icon">
                    <i class="far fa-clock"></i>
                  </span>
                  <span class="post-meta-item-text">阅读时长 &asymp;</span>
                  <span>4 分钟</span>
                </span>
              </div>
            </article>
            <article itemscope itemtype="http://schema.org/Article" class="post-block index" lang="zh-CN">
              <link itemprop="mainEntityOfPage" href="https://cuiqingcai.com/23851.html">
              <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
                <meta itemprop="image" content="/images/avatar.png">
                <meta itemprop="name" content="崔庆才">
                <meta itemprop="description" content="崔庆才的个人站点，记录生活的瞬间，分享学习的心得。">
              </span>
              <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
                <meta itemprop="name" content="静觅">
              </span>
              <header class="post-header">
                <h2 class="post-title" itemprop="name headline">
                  <a class="label"> 技术杂谈 <i class="label-arrow"></i>
                  </a>
                  <a href="/23851.html" class="post-title-link" itemprop="url">Vue生产环境如何还原debugger</a>
                </h2>
              </header>
              <div class="post-body" itemprop="articleBody">
                <div class="thumb">
                  <img itemprop="contentUrl" class="random">
                </div>
                <div class="excerpt">
                  <p>
                  <p>最近刚遇到个问题，我要给自己做的网站加个无限 debugger 反爬，网站是基于 Vue.js 开发的，比如我就想在 main.js 里面加这么一段：</p>
                  <figure class="highlight javascript">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line">setInterval(<span class="function"><span class="params">()</span> =&gt;</span> &#123;</span><br><span class="line">  <span class="keyword">debugger</span></span><br><span class="line">  <span class="built_in">console</span>.log(<span class="string">'debugger'</span>)</span><br><span class="line">&#125;, <span class="number">1000</span>)</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>当时在 Debug 环境下一切好好的，但是到了 build 之后，再运行发现 debugger 就没了，这就神奇了。</p>
                  <p>我搜了很久，最后终于找到了解决方案，这里记录下。</p>
                  <h2 id="开发环境和生产环境"><a href="#开发环境和生产环境" class="headerlink" title="开发环境和生产环境"></a>开发环境和生产环境</h2>
                  <p>这里首先说下 Vue.js 是有开发环境和生产环境之分的，这里它用了一个关键词，叫做 mode。</p>
                  <p>我们先来看看两个常用的命令：</p>
                  <figure class="highlight dockerfile">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line">npm <span class="keyword">run</span><span class="bash"> serve</span></span><br><span class="line">npm <span class="keyword">run</span><span class="bash"> build</span></span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>这两个命令如果大家开发 Vue.js 的话一定不会陌生，但它们是怎么实现的呢？</p>
                  <p>顺着一找，其实他们定义在了 package.json 里面，是这样的：</p>
                  <figure class="highlight python">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line">&#123;</span><br><span class="line">  <span class="string">"version"</span>: <span class="string">"0.1.0"</span>,</span><br><span class="line">  <span class="string">"private"</span>: true,</span><br><span class="line">  <span class="string">"scripts"</span>: &#123;</span><br><span class="line">    <span class="string">"serve"</span>: <span class="string">"vue-cli-service serve"</span>,</span><br><span class="line">    <span class="string">"build"</span>: <span class="string">"vue-cli-service build"</span>,</span><br><span class="line">    <span class="string">"lint"</span>: <span class="string">"vue-cli-service lint"</span></span><br><span class="line">  &#125;,</span><br><span class="line">  ...</span><br><span class="line">&#125;</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>这里其实就是调用了 <code>vue-cli-service</code> 的几个命令而已。</p>
                  <p>那 <code>vue-cli-service</code> 又是哪里来的呢？很简单，在刚开始初始化项目的时候装了个 Vue CLI：</p>
                  <figure class="highlight coffeescript">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="built_in">npm</span> install -g @vue/cli</span><br><span class="line"><span class="comment"># OR</span></span><br><span class="line">yarn <span class="built_in">global</span> add @vue/cli</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>它提供了 <code>vue-cli-service</code> 这个命令。</p>
                  <p>然后我们再来详细看看这个 serve 和 build 命令。</p>
                  <h3 id="serve"><a href="#serve" class="headerlink" title="serve"></a>serve</h3>
                  <p>用法如下：</p>
                  <figure class="highlight">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="attribute">Usage</span>: vue-cli-service serve [options] [entry]</span><br><span class="line"></span><br><span class="line"><span class="attribute">Options:</span></span><br><span class="line"><span class="attribute"></span></span><br><span class="line">  --open         open browser on server start</span><br><span class="line">  --copy         copy url to clipboard on server start</span><br><span class="line">  --mode         specify env mode (default: development)</span><br><span class="line">  --host         specify host (default: 0.0.0.0)</span><br><span class="line">  --port         specify port (default: 8080)</span><br><span class="line">  --https        use https (default: false)</span><br><span class="line">  --public       specify the public network URL for the HMR client</span><br><span class="line">  --skip-plugins comma-separated list of plugin names to skip for this run</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>看到了吧，这里有个 mode，指的就是运行环境，这里默认为 development，即开发环境。</p>
                  <h3 id="build"><a href="#build" class="headerlink" title="build"></a>build</h3>
                  <p>用法如下：</p>
                  <figure class="highlight">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="attribute">Usage</span>: vue-cli-service build [options] [entry|pattern]</span><br><span class="line"></span><br><span class="line"><span class="attribute">Options:</span></span><br><span class="line"><span class="attribute"></span></span><br><span class="line">  --mode         specify env mode (default: production)</span><br><span class="line">  --dest         specify output directory (default: dist)</span><br><span class="line">  --modern       build app targeting modern browsers with auto fallback</span><br><span class="line">  --no-unsafe-inline build app without introducing inline scripts</span><br><span class="line">  --target       app | lib | wc | wc-async (default: app)</span><br><span class="line">  --formats      list of output formats for library builds (default: commonjs,umd,umd-min)</span><br><span class="line">  --inline-vue   include the Vue module in the final bundle of library or web component target</span><br><span class="line">  --name         name for lib or web-component mode (default: "name" in package.json or entry filename)</span><br><span class="line">  --filename     file name for output, only usable for 'lib' target (default: value of --name),</span><br><span class="line">  --no-clean     do not remove the dist directory before building the project</span><br><span class="line">  --report       generate report.html to help analyze bundle content</span><br><span class="line">  --report-json  generate report.json to help analyze bundle content</span><br><span class="line">  --skip-plugins comma-separated list of plugin names to skip for this run</span><br><span class="line">  --watch        watch for changes</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>这里也有一个 mode，默认就是 production 了，即生产环境。</p>
                  <p>所以，到这里我们就明白了，调用 build 命令之后，实际上是生产环境了，然后生产环境可能做了一些特殊的配置，把一些 debugger 给去除了，所以就没了。</p>
                  <h2 id="还原"><a href="#还原" class="headerlink" title="还原"></a>还原</h2>
                  <p>那咋还原呢？</p>
                  <p>这里我们就需要用到 Vue.js 的另外一个知识了。</p>
                  <p>Vue.js 同样是基于 Webpack 构建的，利用了 Webpack 的打包技术，不过为了更加方便开发者配置，Vue.js 在 Webpack 的基础上又封装了一层，一些配置我们不需要再实现 webpack.config.js 了，而是可以实现 vue.config.js，配置更加简单。</p>
                  <p>在 vue.config.js 里面，它为 Webpack 暴露了几个重要的配置入口，一个就是 configureWebpack，一个是 chainWebpack。</p>
                  <p>具体的教程大家可以参考官方文档：<a href="https://cli.vuejs.org/zh/guide/webpack.html。" target="_blank" rel="noopener">https://cli.vuejs.org/zh/guide/webpack.html。</a></p>
                  <p>比如前者可以这么配置：</p>
                  <figure class="highlight javascript">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="built_in">module</span>.exports = &#123;</span><br><span class="line">  configureWebpack: &#123;</span><br><span class="line">    plugins: [</span><br><span class="line">      <span class="keyword">new</span> MyAwesomeWebpackPlugin()</span><br><span class="line">    ]</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>后者可以这么配置：</p>
                  <figure class="highlight javascript">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="comment">// vue.config.js</span></span><br><span class="line"><span class="built_in">module</span>.exports = &#123;</span><br><span class="line">  chainWebpack: <span class="function"><span class="params">config</span> =&gt;</span> &#123;</span><br><span class="line">    config.module</span><br><span class="line">      .rule(<span class="string">'vue'</span>)</span><br><span class="line">      .use(<span class="string">'vue-loader'</span>)</span><br><span class="line">        .loader(<span class="string">'vue-loader'</span>)</span><br><span class="line">        .tap(<span class="function"><span class="params">options</span> =&gt;</span> &#123;</span><br><span class="line">          <span class="keyword">return</span> options</span><br><span class="line">        &#125;)</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>这里，我们如果要修改 Webpack 构建的一些配置的话，可以利用 chainWebpack。</p>
                  <h2 id="TerserPlugin"><a href="#TerserPlugin" class="headerlink" title="TerserPlugin"></a>TerserPlugin</h2>
                  <p>然后，这里又需要引入另外一个 Webpack 插件了，叫做 TerserPlugin，官方介绍链接为 <a href="https://webpack.js.org/plugins/terser-webpack-plugin/。" target="_blank" rel="noopener">https://webpack.js.org/plugins/terser-webpack-plugin/。</a></p>
                  <p>而这个库又是依赖 terser 的，官方介绍链接为 <a href="https://github.com/terser/terser。" target="_blank" rel="noopener">https://github.com/terser/terser。</a></p>
                  <p>官方介绍为：</p>
                  <blockquote>
                    <p>A JavaScript parser and mangler/compressor toolkit for ES6+.</p>
                  </blockquote>
                  <p>OK，反正就是类似一个 JavaScript 压缩转换器，比如它可以将一些 JavaScript 代码转码、混淆、压缩等等。</p>
                  <p>这里我们就需要借助于它来实现 debugger 的还原。</p>
                  <p>这里由于我使用的 Webpack 是 4.x 版本，所以 TerserPlugin 也需要是 4.x 版本，5.x 版本我测试过了不行。</p>
                  <p>安装配置如下，添加到 package.json 的 devDependencies 里面：</p>
                  <figure class="highlight 1c">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="string">"terser-webpack-plugin"</span>: <span class="string">"^4.2.3"</span>,</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>然后：</p>
                  <figure class="highlight cmake">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line">npm <span class="keyword">install</span></span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>接着 vue.config.js 改写如下：</p>
                  <figure class="highlight python">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line">const TerserPlugin = require(<span class="string">'terser-webpack-plugin'</span>)</span><br><span class="line">module.exports = &#123;</span><br><span class="line">  ...</span><br><span class="line">  productionSourceMap: false,</span><br><span class="line">  chainWebpack: config =&gt; &#123;</span><br><span class="line">    config.optimization.minimizer([</span><br><span class="line">        new TerserPlugin(&#123;</span><br><span class="line">          terserOptions: &#123;</span><br><span class="line">            mangle: true,</span><br><span class="line">            compress: &#123;</span><br><span class="line">              drop_debugger: false</span><br><span class="line">            &#125;</span><br><span class="line">          &#125;</span><br><span class="line">        &#125;)</span><br><span class="line">      ]</span><br><span class="line">    )</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>这里我就保留了 chainWebpack 的配置，然后这里面通过 config 的 optimization 的 minimizer 方法配置了 plugins，然后这里 TerserPlugin 需要声明一个 terserOptions，然后 compress 里面的 drop_debugger 需要设置为 false。</p>
                  <p>这样，生产环境的 debugger 语句就不会丢了。</p>
                  </p>
                </div>
              </div>
              <div class="post-meta">
                <span class="post-meta-item">
                  <span class="post-meta-item-icon">
                    <i class="far fa-user"></i>
                  </span>
                  <span class="post-meta-item-text">作者</span>
                  <span><a href="/authors/崔庆才" class="author" itemprop="url" rel="index">崔庆才</a></span>
                </span>
                <span class="post-meta-item">
                  <span class="post-meta-item-icon">
                    <i class="far fa-calendar"></i>
                  </span>
                  <span class="post-meta-item-text">发表于</span>
                  <time title="创建时间：2020-10-28 23:02:43" itemprop="dateCreated datePublished" datetime="2020-10-28T23:02:43+08:00">2020-10-28</time>
                </span>
                <span id="/23851.html" class="post-meta-item leancloud_visitors" data-flag-title="Vue生产环境如何还原debugger" title="阅读次数">
                  <span class="post-meta-item-icon">
                    <i class="fa fa-eye"></i>
                  </span>
                  <span class="post-meta-item-text">阅读次数：</span>
                  <span class="leancloud-visitors-count"></span>
                </span>
                <span class="post-meta-item" title="本文字数">
                  <span class="post-meta-item-icon">
                    <i class="far fa-file-word"></i>
                  </span>
                  <span class="post-meta-item-text">本文字数：</span>
                  <span>3.8k</span>
                </span>
                <span class="post-meta-item" title="阅读时长">
                  <span class="post-meta-item-icon">
                    <i class="far fa-clock"></i>
                  </span>
                  <span class="post-meta-item-text">阅读时长 &asymp;</span>
                  <span>3 分钟</span>
                </span>
              </div>
            </article>
            <article itemscope itemtype="http://schema.org/Article" class="post-block index" lang="zh-CN">
              <link itemprop="mainEntityOfPage" href="https://cuiqingcai.com/23850.html">
              <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
                <meta itemprop="image" content="/images/avatar.png">
                <meta itemprop="name" content="崔庆才">
                <meta itemprop="description" content="崔庆才的个人站点，记录生活的瞬间，分享学习的心得。">
              </span>
              <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
                <meta itemprop="name" content="静觅">
              </span>
              <header class="post-header">
                <h2 class="post-title" itemprop="name headline">
                  <a class="label"> 技术杂谈 <i class="label-arrow"></i>
                  </a>
                  <a href="/23850.html" class="post-title-link" itemprop="url">1024，其实我想聊一聊程序员的标签化</a>
                </h2>
              </header>
              <div class="post-body" itemprop="articleBody">
                <div class="thumb">
                  <img itemprop="contentUrl" class="random">
                </div>
                <div class="excerpt">
                  <p>
                  <p>2019 年，网红王尼玛做了一个五分钟的视频，是有关程序员的综艺节目《创造1024》，视频冲上热搜，被转发了几十万次，而这个视频，通篇是对程序员的刻板印象和标签化再加深。</p>
                  <p>视频里，程序员是这样子的：</p>
                  <p><img src="https://qiniu.cuiqingcai.com/p0j8w.png" alt=""></p>
                  <p>视频里面每个程序员都是标配的黑眼圈，更有甚者那个连续七天七夜不眠不休最后累倒的程序员被推崇为 C 位大佬。「没女朋友」、「宅男」、「呆板」、「理工男」、「格子衫」、「没头发」 等等这些标签。</p>
                  <p>我不是吐槽视频本身，通过这个视频，站在另外的角度去思考，这里面确实有很多让我感觉不那么舒服的地方。</p>
                  <ul>
                    <li>第一，把女性程序员排除在外；</li>
                    <li>第二，把整个行业的形象刻画的呆板、邋遢；</li>
                    <li>第三，为什么程序员就一定会被标签化为这样的形象；</li>
                  </ul>
                  <p>有的时候真的非常伤心，互联网时代真的来临了，程序员这个行业走上台前了。</p>
                  <p>然而走上台前的，不是曾经想用产品改变世界的梦想，而是秃头、加班、格子衫。</p>
                  <p>看到一些微博还有这样的：</p>
                  <p><img src="https://qiniu.cuiqingcai.com/vwqmd.png" alt=""></p>
                  <p>所以一直到现在，我都对格子衫有着非常深刻的生理性反感，我有条纹衬衫，也有花衬衫，但就是不喜欢格子衫，因为每当我去穿格子衫的时候，我就觉得我走进了公众预设定的无聊框架中。因此，每当女朋友陪我买衣服的时候，路过格子衫的区域，我一定不会去选。</p>
                  <p>嘿嘿没错，我还有女朋友，谁说程序员没有女朋友的？况且，我女朋友还那么好看。</p>
                  <p>哦哦跑题了，说回格子衫，我现在选择不穿格子衫，其实也是被框架捆绑的一部分，可我又能怎么办呢？</p>
                  <p>当然，logo卫衣还是很赞。</p>
                  <p>当然，在提到程序员这个行业的时候，最大也是最让我讨厌的刻板影响，叫程序员安慰师。</p>
                  <p>程序员安慰师这个所谓的行业和所谓的热搜热转出来的时候，是我觉得最荒谬的事情，到底是谁觉得我们的智商和情商，我们对工作的热情和严谨，是被女性带动的。每个男性都喜欢漂亮的女孩，这是原始的性，但在这之上，我们如此优秀完成工作的事情，是我们聪明的大脑（掐腰）。</p>
                  <p>最后我想说，我仍然能看到有非常多的调研报告，有越来越多的小姐姐开始在相亲中去倾向程序员这个行业。</p>
                  <p>但我想说，所谓高薪，所谓单纯，所谓不会出轨，都是外界给我们的一个个贴下的标签，而在这标签下，我们仍然是独立而特别的个体。希望你最后的选择是因为我这个人，而并不是那些无聊的刻板印象。</p>
                  <p>我们程序员并不一定是秃头、呆滞、毫无生活情趣的死肥宅，至少说很多都不是，我们也有可爱的一面，也有自己热爱的生活，喜欢的人，喜欢的事，请行业不要再这么标签化我们。</p>
                  <p>1024，我既不想接受格子衫与人体工学椅的安利，也不想接受任何《程序员图鉴》的调侃。我希望节日能让公司反思过高强度的加班，我希望节日能给更多的人传输目前程序届的开源思想，我希望节日能让人们回忆起，在疫情时候，有那么多个体的程序员不记薪资帮助做统计和维护框架，我希望节日能让更多人意识到我们每一个有灵魂的个体本身。</p>
                  <p>最后，整篇发言稿都是我的一家之言，是我的三观输出，可能会有很多朋友不习惯或者不开心。用程序码出世界，始终是我的理想。</p>
                  <p>无论如何，祝大家 1024 节日快乐！</p>
                  </p>
                </div>
              </div>
              <div class="post-meta">
                <span class="post-meta-item">
                  <span class="post-meta-item-icon">
                    <i class="far fa-user"></i>
                  </span>
                  <span class="post-meta-item-text">作者</span>
                  <span><a href="/authors/崔庆才" class="author" itemprop="url" rel="index">崔庆才</a></span>
                </span>
                <span class="post-meta-item">
                  <span class="post-meta-item-icon">
                    <i class="far fa-calendar"></i>
                  </span>
                  <span class="post-meta-item-text">发表于</span>
                  <time title="创建时间：2020-10-24 21:37:43" itemprop="dateCreated datePublished" datetime="2020-10-24T21:37:43+08:00">2020-10-24</time>
                </span>
                <span id="/23850.html" class="post-meta-item leancloud_visitors" data-flag-title="1024，其实我想聊一聊程序员的标签化" title="阅读次数">
                  <span class="post-meta-item-icon">
                    <i class="fa fa-eye"></i>
                  </span>
                  <span class="post-meta-item-text">阅读次数：</span>
                  <span class="leancloud-visitors-count"></span>
                </span>
                <span class="post-meta-item" title="本文字数">
                  <span class="post-meta-item-icon">
                    <i class="far fa-file-word"></i>
                  </span>
                  <span class="post-meta-item-text">本文字数：</span>
                  <span>1.2k</span>
                </span>
                <span class="post-meta-item" title="阅读时长">
                  <span class="post-meta-item-icon">
                    <i class="far fa-clock"></i>
                  </span>
                  <span class="post-meta-item-text">阅读时长 &asymp;</span>
                  <span>1 分钟</span>
                </span>
              </div>
            </article>
            <article itemscope itemtype="http://schema.org/Article" class="post-block index" lang="zh-CN">
              <link itemprop="mainEntityOfPage" href="https://cuiqingcai.com/23185.html">
              <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
                <meta itemprop="image" content="/images/avatar.png">
                <meta itemprop="name" content="崔庆才">
                <meta itemprop="description" content="崔庆才的个人站点，记录生活的瞬间，分享学习的心得。">
              </span>
              <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
                <meta itemprop="name" content="静觅">
              </span>
              <header class="post-header">
                <h2 class="post-title" itemprop="name headline">
                  <a href="/23185.html" class="post-title-link" itemprop="url">使用Hexo编写博客</a>
                </h2>
              </header>
              <div class="post-body" itemprop="articleBody">
                <div class="thumb">
                  <img itemprop="contentUrl" class="random">
                </div>
                <div class="excerpt">
                  <p>
                  <h1 id="使用Hexo编写博客？"><a href="#使用Hexo编写博客？" class="headerlink" title="使用Hexo编写博客？"></a>使用Hexo编写博客？</h1>
                  <blockquote>
                    <p>亲爱的伙伴您好，很荣幸能与您在此相遇.</p>
                    <p>本文主要用于记录，在一台完全的“新”机子上，书写Hexo部署博客。</p>
                    <p>我已经迫不及待想告诉你的几个容易错误的点，你准备好了么？</p>
                    <p>Let’s Go</p>
                    <p>在此之前说明，很多东西都是来自网络，当然无论如何还是建议你查阅官方文档。</p>
                  </blockquote>
                  <p><a href="https://hexo.io/zh-cn/docs/" target="_blank" rel="noopener">Hexo</a>官方文档</p>
                  <h2 id="Fisrt-环境准备"><a href="#Fisrt-环境准备" class="headerlink" title="Fisrt  环境准备"></a>Fisrt 环境准备</h2>
                  <ul>
                    <li>[ ] Git</li>
                    <li>[ ] <a href="http://nodejs.org/" target="_blank" rel="noopener">Node.js</a> (Node.js 版本需不低于 10.13，建议使用 Node.js 12.0 及以上版本)</li>
                    <li>[ ] Hexo</li>
                  </ul>
                  <h3 id="Git："><a href="#Git：" class="headerlink" title="Git："></a>Git：</h3>
                  <p>可以参考此文章 <a href="https://cuiqingcai.com/9336.html">https://cuiqingcai.com/9336.html</a></p>
                  <blockquote>
                    <p><strong>Mac 用户</strong></p>
                    <p>如果在编译时可能会遇到问题，请先到 App Store 安装 Xcode，Xcode 完成后，启动并进入 <strong>Preferences -&gt; Download -&gt; Command Line Tools -&gt; Install</strong> 安装命令行工具。</p>
                  </blockquote>
                  <h3 id="Node-JS"><a href="#Node-JS" class="headerlink" title="Node.JS:"></a>Node.JS:</h3>
                  <p>Node.js 为大多数平台提供了官方的 <a href="https://nodejs.org/en/download/" target="_blank" rel="noopener">安装程序</a>。对于中国大陆地区用户，可以前往 <a href="https://npm.taobao.org/mirrors/node" target="_blank" rel="noopener">淘宝 Node.js 镜像</a> 下载。</p>
                  <p>其它的安装方法：</p>
                  <ul>
                    <li>Windows：通过 <a href="https://github.com/jasongin/nvs/" target="_blank" rel="noopener">nvs</a>（推荐）或者<a href="https://github.com/nvm-sh/nvm" target="_blank" rel="noopener">nvm</a> 安装。</li>
                    <li>Mac：使用 <a href="https://brew.sh/" target="_blank" rel="noopener">Homebrew</a> 或 <a href="http://www.macports.org/" target="_blank" rel="noopener">MacPorts</a> 安装。</li>
                    <li>Linux（DEB/RPM-based）：从 <a href="https://github.com/nodesource/distributions" target="_blank" rel="noopener">NodeSource</a> 安装。</li>
                    <li>其它：使用相应的软件包管理器进行安装，可以参考由 Node.js 提供的 <a href="https://nodejs.org/en/download/package-manager/" target="_blank" rel="noopener">指导</a></li>
                  </ul>
                  <h3 id="Hexo："><a href="#Hexo：" class="headerlink" title="Hexo："></a>Hexo：</h3>
                  <blockquote>
                    <p>所有必备的应用程序安装完成后，即可使用 npm 安装 Hexo。</p>
                  </blockquote>
                  <figure class="highlight plain">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"># 和我一样小白的可使用以下命令来安装</span><br><span class="line">npm install -g hexo-cli</span><br><span class="line"># 对于熟悉 npm 的大牛，可以仅局部安装 hexo 包。</span><br><span class="line">npm install hexo</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <h3 id="验证安装"><a href="#验证安装" class="headerlink" title="验证安装"></a>验证安装</h3>
                  <figure class="highlight applescript">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="comment"># 注意请不要在项目中使用，可能会因为限制从而导致验证误差</span></span><br><span class="line">hexo <span class="built_in">version</span></span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>Look </p>
                  <p><img src="https://tva1.sinaimg.cn/large/007S8ZIlgy1gjsryfevu8j30ks0bs41p.jpg" alt="Hexo Version"></p>
                  <h2 id="Second-写作"><a href="#Second-写作" class="headerlink" title="Second  写作"></a>Second 写作</h2>
                  <h3 id="新建"><a href="#新建" class="headerlink" title="新建"></a>新建</h3>
                  <figure class="highlight sh">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="comment"># 创建一篇新文章或者新的页面</span></span><br><span class="line">hexo new [layout] &lt;title&gt;</span><br><span class="line"><span class="comment"># EG  注意双引号中的是博客标题，不需要加.md等后缀。</span></span><br><span class="line">hexo new <span class="string">"Your Title"</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># hexo new --help</span></span><br><span class="line">Usage: hexo new [layout] &lt;title&gt;</span><br><span class="line"></span><br><span class="line">Description:</span><br><span class="line">Create a new post.</span><br><span class="line"></span><br><span class="line">Arguments:</span><br><span class="line">  layout  Post layout. Use post, page, draft or whatever you want.</span><br><span class="line">  title   Post title. Wrap it with quotations to escape.</span><br><span class="line"></span><br><span class="line">Options:</span><br><span class="line">  -p, --path     Post path. Customize the path of the post.</span><br><span class="line">  -r, --replace  Replace the current post <span class="keyword">if</span> existed.</span><br><span class="line">  -s, --slug     Post slug. Customize the URL of the post.</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <blockquote>
                    <p>Hexo 有三种默认布局：<code>post</code>、<code>page</code> 和 <code>draft</code>。在创建者三种不同类型的文件时，它们将会被保存到不同的路径；而您自定义的其他布局和 <code>post</code> 相同，都将储存到 <code>source/_posts</code> 文件夹。</p>
                    <div class="table-container">
                      <table>
                        <thead>
                          <tr>
                            <th style="text-align:left">布局</th>
                            <th style="text-align:left">路径</th>
                          </tr>
                        </thead>
                        <tbody>
                          <tr>
                            <td style="text-align:left"><code>post</code></td>
                            <td style="text-align:left"><code>source/_posts</code></td>
                          </tr>
                          <tr>
                            <td style="text-align:left"><code>page</code></td>
                            <td style="text-align:left"><code>source</code></td>
                          </tr>
                          <tr>
                            <td style="text-align:left"><code>draft</code></td>
                            <td style="text-align:left"><code>source/_drafts</code></td>
                          </tr>
                        </tbody>
                      </table>
                    </div>
                  </blockquote>
                  <h3 id="文内设置"><a href="#文内设置" class="headerlink" title="文内设置"></a>文内设置</h3>
                  <p>用markdown等编辑器写博客，tags的写法如下：</p>
                  <figure class="highlight sh">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="comment"># 注意冒号与方括号之间有一个空格，方括号中的标签用英文的”,”</span></span><br><span class="line">tags: [hexo,备忘录]</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <h4 id="添加“阅读全文”按钮"><a href="#添加“阅读全文”按钮" class="headerlink" title="添加“阅读全文”按钮"></a><strong>添加“阅读全文”按钮</strong></h4>
                  <p>方法一：</p>
                  <figure class="highlight sh">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="comment"># 在文章任意你想添加的位置添加</span></span><br><span class="line">&lt;!--more--&gt;</span><br><span class="line"><span class="comment"># EG</span></span><br><span class="line"></span><br><span class="line">---</span><br><span class="line">title: How to use hexo to create blog?</span><br><span class="line">date: 2020-10-17 01:48:53</span><br><span class="line">author:Payne</span><br><span class="line">Mail:wuzhipeng1289690157@gamil.com</span><br><span class="line">tags:[Hexo]</span><br><span class="line">---</span><br><span class="line">&lt;!--more--&gt;</span><br><span class="line">后面的内容在首页不显示，只显示到&lt;!--more--&gt;这里</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>方法二：</p>
                  <figure class="highlight yaml">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="comment"># 设置首页文章以摘要形式显示，打开主题配置文件，找到auto_excerpt进行修改</span></span><br><span class="line"><span class="attr">auto_excerpt:</span></span><br><span class="line">  <span class="attr">enable:</span> <span class="literal">true</span></span><br><span class="line">  <span class="attr">length:</span> <span class="number">150</span></span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <blockquote>
                    <p>其中length代表显示摘要的截取字符长度。<br>注：这两种方法，在博客首页显示的效果不一样，根据自己的需要，选择自己喜欢的方法</p>
                  </blockquote>
                  <p>请开始您的表演😊</p>
                  <p>Show Time 。。。</p>
                  <h2 id="Third-自我查阅"><a href="#Third-自我查阅" class="headerlink" title="Third  自我查阅"></a>Third 自我查阅</h2>
                  <figure class="highlight vala">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="meta"># 构建 -&gt; 用于生成博客的html文件</span></span><br><span class="line">hexo g</span><br><span class="line"><span class="meta"># 预览 -&gt; 用于在本地预览博客，打开浏览器，输入 localhost:4000/ 即可查看。</span></span><br><span class="line">hexo s</span><br><span class="line"><span class="meta"># 检查博客格式等符合要求后，用此命令将博客推送到远端。(需要是自己的才行)</span></span><br><span class="line">hexo d</span><br><span class="line"></span><br><span class="line"><span class="meta"># 实操</span></span><br><span class="line"><span class="meta"># 构建并查阅</span></span><br><span class="line">hexo g &amp;&amp; hexo s</span><br><span class="line"><span class="meta"># 推送（记得清除缓存！！！）</span></span><br><span class="line">hexo clean &amp;&amp; hexo g &amp;&amp; hexo d</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p><img src="https://tva1.sinaimg.cn/large/007S8ZIlgy1gjsrwob2sgj31280u0e59.jpg" alt="images"></p>
                  <h2 id="Fourth-发布"><a href="#Fourth-发布" class="headerlink" title="Fourth 发布"></a>Fourth 发布</h2>
                  <figure class="highlight sh">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="comment"># 详细流程如下</span></span><br><span class="line">首先<span class="built_in">clone</span>下来然后，创建分支</span><br><span class="line">git <span class="built_in">clone</span> <span class="string">"目标地址"</span></span><br><span class="line">git checkout -b branch_name</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment"># 编写博客</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment"># 构建并查阅</span></span><br><span class="line">hexo g &amp;&amp; hexo s</span><br><span class="line"><span class="comment"># 推送（记得清除缓存！！！）</span></span><br><span class="line">hexo clean &amp;&amp; hexo g &amp;&amp; hexo d</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  </p>
                </div>
              </div>
              <div class="post-meta">
                <span class="post-meta-item">
                  <span class="post-meta-item-icon">
                    <i class="far fa-calendar"></i>
                  </span>
                  <span class="post-meta-item-text">发表于</span>
                  <time title="创建时间：2020-10-18 00:18:25" itemprop="dateCreated datePublished" datetime="2020-10-18T00:18:25+08:00">2020-10-18</time>
                </span>
                <span id="/23185.html" class="post-meta-item leancloud_visitors" data-flag-title="使用Hexo编写博客" title="阅读次数">
                  <span class="post-meta-item-icon">
                    <i class="fa fa-eye"></i>
                  </span>
                  <span class="post-meta-item-text">阅读次数：</span>
                  <span class="leancloud-visitors-count"></span>
                </span>
                <span class="post-meta-item" title="本文字数">
                  <span class="post-meta-item-icon">
                    <i class="far fa-file-word"></i>
                  </span>
                  <span class="post-meta-item-text">本文字数：</span>
                  <span>2.2k</span>
                </span>
                <span class="post-meta-item" title="阅读时长">
                  <span class="post-meta-item-icon">
                    <i class="far fa-clock"></i>
                  </span>
                  <span class="post-meta-item-text">阅读时长 &asymp;</span>
                  <span>2 分钟</span>
                </span>
              </div>
            </article>
            <article itemscope itemtype="http://schema.org/Article" class="post-block index" lang="zh-CN">
              <link itemprop="mainEntityOfPage" href="https://cuiqingcai.com/10241.html">
              <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
                <meta itemprop="image" content="/images/avatar.png">
                <meta itemprop="name" content="崔庆才">
                <meta itemprop="description" content="崔庆才的个人站点，记录生活的瞬间，分享学习的心得。">
              </span>
              <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
                <meta itemprop="name" content="静觅">
              </span>
              <header class="post-header">
                <h2 class="post-title" itemprop="name headline">
                  <a class="label"> 技术杂谈 <i class="label-arrow"></i>
                  </a>
                  <a href="/10241.html" class="post-title-link" itemprop="url">近学习分布式感想随笔</a>
                </h2>
              </header>
              <div class="post-body" itemprop="articleBody">
                <div class="thumb">
                  <img itemprop="contentUrl" class="random">
                </div>
                <div class="excerpt">
                  <p>
                  <h2 id="Abstract"><a href="#Abstract" class="headerlink" title="Abstract"></a><strong>Abstract</strong></h2>
                  <blockquote>
                    <p>随着大数据人工智能时代的来临，互联网的快速发展。许许多多以前可能并不那么实际或需要的算法、技术也逐渐进入我们的眼中。例如分布式、集群、负载均衡、也越来越“平民”化。近期重新再一次的对于分布式理念、思想进行了学习。此随笔也因此而来。请多指教 为什么需要分布式？ 什么是分布式？ 分布式的核心理念是什么？ 如何实现分布式、负载均衡、集群？</p>
                  </blockquote>
                  <h2 id="Why-distributed？"><a href="#Why-distributed？" class="headerlink" title="Why distributed？"></a>Why distributed？</h2>
                  <blockquote>
                    <p>为什么需要分布式、集群、负载均衡？</p>
                  </blockquote>
                  <p>概念的提出或理论的出现，一定是为了解决对应的问题或避免相对应的问题。使其不断的完善化、稳定化。毕竟Human nature is lazy 此时此刻可能更需要什么?（3V3H)</p>
                  <ul>
                    <li>Volume 海量</li>
                    <li>Variety 多样</li>
                    <li>velocity 实时</li>
                    <li>高并发</li>
                    <li>高可扩</li>
                    <li>高性能</li>
                  </ul>
                  <p>单机可能将会遇到的问题会有</p>
                  <ul>
                    <li>系统容量</li>
                    <li>单点故障</li>
                    <li>性能不足</li>
                    <li>…</li>
                  </ul>
                  <p>该如何解决此问题? 有一种比较功利性的思想-缺啥补啥，当然也是比较较为明确的方式。至少我仅仅只需要解决以上中较少问题。 分布式（思想）要解决的问题主要是单机系统中系统容量不足及提高系统可用性。</p>
                  <h2 id="What‘s-Distributed？"><a href="#What‘s-Distributed？" class="headerlink" title="What‘s Distributed？"></a>What‘s Distributed？</h2>
                  <blockquote>
                    <p>什么是分布式？亦或者说满足如何的条件才算分布式？</p>
                  </blockquote>
                  <p>分布式（系统），简而言之即是由多个处理机通过通信路线互联而构成的松散。一次性近乎解决了所有单点的所有问题。</p>
                  <blockquote>
                    <p>A distributed system is a system whose components are located on different networked computers, which communicate and coordinate their actions by passing messages to one another.[1] The components interact with one another in order to achieve a common goal. Three significant characteristics of distributed systems are: concurrency of components, lack of a global clock, and independent failure of components.[1] Examples of distributed systems vary from SOA-based systems to massively multiplayer online games to peer-to-peer applications.</p>
                  </blockquote>
                  <p>个人认为高并发、高可扩、高性能以此为主推到出 并发性：一个大的任务可以划分为若干个子任务，分别在不同的主机上执行 可扩性：可弹性增降容 自治性：分布式系统中的各个节点都包含自己的处理机和内存，各自具有独立的处理数据的功能。通常，彼此在地位上是平等的，无主次之分，既能自治地进行工作，又能利用共享的通信线路来传送信息，协调任务处理 全局唯一性：分布式系统中必须存在一个单一的、全局的进程通信机制，使得任何一个进程都能与其他进程通信，并且不区分本地通信与远程通信。</p>
                  <h2 id="What-is-the-core-idea-of-distribution"><a href="#What-is-the-core-idea-of-distribution" class="headerlink" title="What is the core idea of distribution?"></a>What is the core idea of distribution?</h2>
                  <blockquote>
                    <p>分布式的核心理念是什么？</p>
                  </blockquote>
                  <p>较于以上的了解，那么最为重要的为： 一致性：各主从机权限可不同、但需有一致性。建立维持自己的通信 容错性：拥有较为自主的稳定性，可能最大保障系统的正常运行</p>
                  <h2 id="How-to-realize-distributed？"><a href="#How-to-realize-distributed？" class="headerlink" title="How to realize distributed？"></a>How to realize distributed？</h2>
                  <blockquote>
                    <p>如何实现分布式？</p>
                  </blockquote>
                  <p>经过了解与探究，相信你已经抓住的有单机到多机（分布式）的命脉，那就是一致性，信号一致性。如果能想到这里，那么恭喜您，你和我一样还是比较需要去学习的。并没有去否定它的正确与否，仅仅是太过于笼统。 <strong>那么既然需要实现分布式，那么仅仅需要建立及维护此通信即可。保障它，你我就从单机的电脑插上了网线。是否有点feel呢？</strong></p>
                  <h2 id="分布式优缺点剖析"><a href="#分布式优缺点剖析" class="headerlink" title="分布式优缺点剖析"></a>分布式优缺点剖析</h2>
                  <blockquote>
                    <p>部分先后，仅从不同角度侧重概述。合而为一即可</p>
                  </blockquote>
                  <p>闪光点： 稳定性：资源共享。若干不同的节点通过通信网络彼此互联，一个节点上的用户可以使用其他节点上的资源。 性能：加快计算速度 机会点 存在通信网络饱和或信息丢失和网络安全问题</p>
                  <h2 id="RAFT"><a href="#RAFT" class="headerlink" title="RAFT"></a>RAFT</h2>
                  <h3 id="简介"><a href="#简介" class="headerlink" title="简介"></a>简介</h3>
                  <p>Raft首先选举出一个server作为Leader，然后赋予它管理日志的全部责任。Leader从客户端接收日志条目，复制给其他server，并告诉他们什么时候可以安全的将日志条目应用到自己的状态机上。拥有一个Leader可以简化replicated log的管理。例如，leader可以决定将新的日志条目放在什么位置，而无需询问其他节点，数据总是简单的从leader流向其他节点。Leader可能失败或者断开连接，这种情况下会选出一个新的leader。 通过leader，Raft将一致性问题分解成三个相当独立的子问题：</p>
                  <ul>
                    <li>Leader Election：当集群启动或者leader失效时必须选出一个新的leader。</li>
                    <li>Log Replication：leader必须接收客户端提交的日志，并将其复制到集群中的其他节点，强制其他节点的日志与leader一样。</li>
                    <li>Safety：最关键的安全点就是图3.2中的State Machine Safety Property。如果任何一个server已经在它的状态机apply了一条日志，其他的server不可能在相同的index处apply其他不同的日志条目。后面将会讲述raft如何实现这一点。</li>
                  </ul>
                  <h3 id="基础"><a href="#基础" class="headerlink" title="基础"></a><strong>基础</strong></h3>
                  <p>一个Raft集群会包含数个server，5是一个典型值，可以容忍两个节点失效。在任何时候每个server都会处于Leader、Candidate、Follower三种状态中的一种。在正常情况下会只有一个leader，其他节点都是follower，follower是消极的，他们不会主动发出请求而仅仅对来自leader和candidate的请求作出回应。leader处理所有来自客户端的请求(如果客户端访问follower，会把请求重定向到follower)。Candidate状态用来选举出一个leader。 多个candidate想要成为leader，如果一个candidate赢得选举，它将会在剩余的term中作为leader。在一些情况下选票可能会被瓜分，导致没有leader产生，这个term将会以没有leader结束，一个新的term将会很快产生。Raft确保每个term至多有一个leader。Term在Raft中起到了逻辑时钟的作用，它可以帮助server检测过期信息比如过期的leader。每一个server都存储有current term字段，会自动随时间增加。当server间通信的时候，会交换current term，如果一个节点的current term比另一个小，它会自动将其更新为较大者。如果candidate或者leader发现了自己的term过期了，它会立刻转为follower状态。如果一个节点收到了一个含有过期的term的请求，它会拒绝该请求。 Raft节点之间通过RPC进行通信，基本的一致性算法仅仅需要两种RPC。RequestVote RPC由candidate在选举过程中发出，AppendEntries RPC由leader发出，用于复制日志和提供心跳。每一个请求类型都有对应的response，Raft假定request和response都可能会丢失，因此要求请求者有超时重试的能力。为了性能，RPC请求会并行发出，而且不保证RPC的到达顺序。</p>
                  <h3 id="Leader-election"><a href="#Leader-election" class="headerlink" title="Leader election"></a><strong>Leader election</strong></h3>
                  <p>Raft使用心跳机制来触发leader选举。当server启动的时候是处于follower状态，当它可以收到来自leader或者candidate的有效RPC请求时就会保持follower的状态。Leader发送周期性的心跳(不含日志的AppendEntries RPC)给所有的follower来确保自己的权威。如果一个follower一段时间(称为election timeout)没有收到消息，它就会假定leader失效并开始新的选举。 为了开始新一轮选举，follower会提高自己当前的term并转为candidate状态。它会先给自己投一票然后并行向集群中的其他server发出RequestVote RPC，candidate会保持这个状态，直到下面三种事情之一发生：</p>
                  <ol>
                    <li>赢得选举。当candidate收到了集群中相同term的多数节点的赞成票时就会选举成功，每一个server在给定的term内至多只能投票给一个candidate，先到先得。收到多数节点的选票可以确保在一个term内至多只能有一个leader选出。一旦一个candidate赢得选举，它就会成为leader。它之后会发送心跳消息来建立自己的权威，并阻止新的选举。</li>
                    <li>另一个server被确定为leader。在等待投票的过程中，candidate可能收到来自其他server的AppendEntries RPC，声明它才是leader。如果RPC中的term大于等于candidate的current term，candidate就会认为这个leader是合法的并转为follower状态。如果RPC中的term比自己当前的小，将会拒绝这个请求并保持candidate状态。</li>
                    <li>没有获胜者产生，等待选举超时。candidate没有选举成功或者失败，如果许多follower同时变成candidate，选票就会被瓜分，形不成多数派。这种情况发生时，candidate将会超时并触发新一轮的选举，提高term并发送新的RequestVote RPC。然而如果不采取其他措施的话，选票将可能会被再次瓜分。</li>
                  </ol>
                  <p>Raft使用随机选举超时来确保选票被瓜分的情况很少出现而且出现了也可以被很快解决。election timeout的值会在一个固定区间内随机的选取(比如150-300ms)。这使得在大部分情况下仅有一个server会超时，它将会在其他节点超时前赢得选举并发送心跳。candidate在发起选举前也会重置自己的随机election timeout，也可以帮助减少新的选举轮次内选票瓜分的情况</p>
                  <h3 id="Log-Replication"><a href="#Log-Replication" class="headerlink" title="Log Replication"></a><strong>Log Replication</strong></h3>
                  <p>一旦一个leader被选举出来，它开始为客户端请求服务。每一个客户端请求都包含着一个待状态机执行的命令，leader会将这个命令作为新的一条日志追加到自己的日志中，然后并行向其他server发出AppendEntries RPC来复制日志。当日志被安全的复制之后，leader可以将日志apply到自己的状态机，并将执行结果返回给客户端。如果follower宕机或运行很慢，甚至丢包，leader会无限的重试RPC(即使已经将结果报告给了客户端)，直到所有的follower最终都存储了相同的日志。 日志按下图的方式进行组织，每一条日志储存了一条命令和leader接收到该指令时的term序号。日志中的term序号可以用来检测不一致的情况，每一条日志也拥有一个整数索引用于定位。</p>
                  <h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2>
                  <p>RAFT算法终究实现了什么？</p>
                  <ul>
                    <li>实现了信号一致性</li>
                    <li>动态的Leader、Accessible or work 角色及节点管理，最大限度的保障了稳定性。</li>
                    <li>他的核心为保障大多数都可用，即可正常运行。</li>
                  </ul>
                  <p>寄语： 如果您是一位非常有经验的管理者或您有相对稳健的算法与数据结构基础， 是否与您所存在的了解的结构有所大多相似呢？-有效管理 直接上司管辖直属同事，算法中的BFS 在稍稍加入较为智能的选Leader，若大多数leader停止了工作，worker 将会进行相对应的“休息”，并没有接受到任务，简单的计算机选择做不如不做。毕竟Human nature is lazy</p>
                  </p>
                </div>
              </div>
              <div class="post-meta">
                <span class="post-meta-item">
                  <span class="post-meta-item-icon">
                    <i class="far fa-user"></i>
                  </span>
                  <span class="post-meta-item-text">作者</span>
                  <span><a href="/authors/Payne" class="author" itemprop="url" rel="index">Payne</a></span>
                </span>
                <span class="post-meta-item">
                  <span class="post-meta-item-icon">
                    <i class="far fa-calendar"></i>
                  </span>
                  <span class="post-meta-item-text">发表于</span>
                  <time title="创建时间：2020-10-07 02:02:04" itemprop="dateCreated datePublished" datetime="2020-10-07T02:02:04+08:00">2020-10-07</time>
                </span>
                <span id="/10241.html" class="post-meta-item leancloud_visitors" data-flag-title="近学习分布式感想随笔" title="阅读次数">
                  <span class="post-meta-item-icon">
                    <i class="fa fa-eye"></i>
                  </span>
                  <span class="post-meta-item-text">阅读次数：</span>
                  <span class="leancloud-visitors-count"></span>
                </span>
                <span class="post-meta-item" title="本文字数">
                  <span class="post-meta-item-icon">
                    <i class="far fa-file-word"></i>
                  </span>
                  <span class="post-meta-item-text">本文字数：</span>
                  <span>4.7k</span>
                </span>
                <span class="post-meta-item" title="阅读时长">
                  <span class="post-meta-item-icon">
                    <i class="far fa-clock"></i>
                  </span>
                  <span class="post-meta-item-text">阅读时长 &asymp;</span>
                  <span>4 分钟</span>
                </span>
              </div>
            </article>
            <article itemscope itemtype="http://schema.org/Article" class="post-block index" lang="zh-CN">
              <link itemprop="mainEntityOfPage" href="https://cuiqingcai.com/10208.html">
              <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
                <meta itemprop="image" content="/images/avatar.png">
                <meta itemprop="name" content="崔庆才">
                <meta itemprop="description" content="崔庆才的个人站点，记录生活的瞬间，分享学习的心得。">
              </span>
              <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
                <meta itemprop="name" content="静觅">
              </span>
              <header class="post-header">
                <h2 class="post-title" itemprop="name headline">
                  <a class="label"> 技术杂谈 <i class="label-arrow"></i>
                  </a>
                  <a href="/10208.html" class="post-title-link" itemprop="url">DockerFile</a>
                </h2>
              </header>
              <div class="post-body" itemprop="articleBody">
                <div class="thumb">
                  <img itemprop="contentUrl" class="random">
                </div>
                <div class="excerpt">
                  <p>
                  <h1 id="Docker-File-解析："><a href="#Docker-File-解析：" class="headerlink" title="Docker File 解析："></a>Docker File 解析：</h1>
                  <h2 id="构建简史"><a href="#构建简史" class="headerlink" title="构建简史"></a>构建简史</h2>
                  <p>编写一个dockerfile的文件，符合dockerfile的规范 docker build 执行，获得一个自定义的镜像 docker 运行 Docker执行docker file文件的大致流程</p>
                  <blockquote>
                    <p>docker 从基础镜像运行一个容器 执行一条指令并对容器作出修改 执行类似docker commit的操作提交一个新的镜像层 docker 在基于刚提交的镜像运行一个新容器 执行docker 中的下一条指令知道所有指令都执行完成</p>
                  </blockquote>
                  <h2 id="Docker-File基础知识："><a href="#Docker-File基础知识：" class="headerlink" title="Docker File基础知识："></a>Docker File基础知识：</h2>
                  <p><img src="https://qiniu.cuiqingcai.com/wp-content/uploads/2020/10/Docker-File镜像表.png" alt=""> 每条<strong>保留字</strong>指令必须为大写字母且后面要跟随至少一个参数 指令从上到下、从左至右执行 ‘#’ ：表示注释 每条指令都会创建一个新的镜像层，并对镜像进行提交</p>
                  <h2 id="Docker-File-体系结构："><a href="#Docker-File-体系结构：" class="headerlink" title="Docker File 体系结构："></a>Docker File 体系结构：</h2>
                  <h3 id="保留字指令："><a href="#保留字指令：" class="headerlink" title="保留字指令："></a>保留字指令：</h3>
                  <p>FROM：基础镜像，当前这个新的镜像是基于哪个镜像（scratch） MAINTAINER：镜像作者+邮箱 RUN：容器构建时所需要运行的命令 EXPOSE：当前容器对外暴露的端口号 WORKDIR：指定在创建容器后，终端默认登陆的进来工作目录，一个落脚点 ENV：用于构建镜像过程中设置环境变量 ADD: 拷贝加解压缩：将宿主机目录下的文件拷贝进镜像且add命令会自动处理rul和解压tar压缩包 COPY:将从构建上下文目录中&lt;源路径&gt;的文件/目录复制到新的一层的镜像内的&lt;目标路径&gt;位置</p>
                  <ul>
                    <li>COPY src dest</li>
                    <li>COPY [“src”,”dest”]</li>
                  </ul>
                  <p>VOLUME:容器数据卷，用于数据保存和持久化工作 CMD：</p>
                  <ul>
                    <li>指定一个容器启动时要运行的命令</li>
                    <li>DockerFile 中可以有多个CMD指令，<strong>但只有最后一个生效</strong>，CMD会被docker run 之后的参数替换！！！</li>
                  </ul>
                  <p>ENTRYPOINT:</p>
                  <ul>
                    <li>指定一个容器启动时要运行的命令</li>
                    <li>目的与CMD一样，都是在指定容器启动程序及参数</li>
                    <li>不会被替换，被追加</li>
                  </ul>
                  <p>ONBUILD：触发器 当构建一个被继承Docker File时运行的命令，父镜像在被子继承后父镜像的onbuild被触发 <img src="https://qiniu.cuiqingcai.com/wp-content/uploads/2020/10/onbuil构造实例1.png" alt=""> <img src="https://qiniu.cuiqingcai.com/wp-content/uploads/2020/10/onbuil构造完成.png" alt=""></p>
                  <h1 id="关键字详解"><a href="#关键字详解" class="headerlink" title="关键字详解"></a>关键字详解</h1>
                  <h2 id="Dockerfile-分为四部分："><a href="#Dockerfile-分为四部分：" class="headerlink" title="Dockerfile 分为四部分："></a>Dockerfile 分为四部分：</h2>
                  <blockquote>
                    <p>基础镜像信息、维护者信息、镜像操作指令和容器启动时执行指令。</p>
                  </blockquote>
                  <h2 id="基础镜像信息"><a href="#基础镜像信息" class="headerlink" title="基础镜像信息"></a>基础镜像信息</h2>
                  <h3 id="FROM"><a href="#FROM" class="headerlink" title="FROM"></a>FROM</h3>
                  <figure class="highlight dts">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="meta"># 格式</span></span><br><span class="line">FROM <span class="params">&lt;image&gt;</span> or FROM <span class="params">&lt;image&gt;</span>:<span class="params">&lt;tag&gt;</span></span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <blockquote>
                    <p>如果在同一个Dockerfile中创建多个镜像时，可以使用多个 <code>FROM</code> 指令（每个镜像一次）</p>
                  </blockquote>
                  <p>注意: Dockerfile每个保留字都会在docker容器中新建一层镜像层, 合理的减少镜像层以达节省资源的目的</p>
                  <figure class="highlight dockerfile">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="comment"># base</span></span><br><span class="line"><span class="keyword">FROM</span> python:<span class="number">3.7</span></span><br><span class="line"><span class="keyword">RUN</span><span class="bash"> pip3 install requests</span></span><br><span class="line"><span class="keyword">RUN</span><span class="bash"> pip3 install bs4</span></span><br><span class="line"><span class="keyword">RUN</span><span class="bash"> pip3 install scrapy</span></span><br><span class="line"><span class="keyword">RUN</span><span class="bash"> ...</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># other</span></span><br><span class="line"><span class="keyword">FROM</span> python:<span class="number">3.7</span></span><br><span class="line"><span class="keyword">RUN</span><span class="bash"> pip3 install requests bs64 scrapy <span class="comment"># Python通过空格分隔,达到安装多个包的效果</span></span></span><br><span class="line"></span><br><span class="line"><span class="comment"># batter</span></span><br><span class="line"><span class="comment"># 外部建立所安装包</span></span><br><span class="line">pip3 freeze &gt;&gt; requirements.txt </span><br><span class="line"><span class="comment"># 在Dockerfile 中</span></span><br><span class="line"><span class="keyword">FROM</span> python:<span class="number">3.7</span></span><br><span class="line"><span class="keyword">RUN</span><span class="bash"> pip3 install -r requirements.txt</span></span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <blockquote>
                    <p>分析: 达到的效果虽相同,但所用资源却不同, base 所使用的资源约为other,batter的3/5</p>
                    <ul>
                      <li>base 三层</li>
                      <li>other 一层</li>
                      <li>batter 一层</li>
                    </ul>
                    <ol>
                      <li>若所需要使用到的第三方库较少,建议使用other</li>
                      <li>在实际工程中用到的第三方库大多情况下都大于三个,方法二虽好.但所需导入的包一多,很可能出现单词拼写错误, 格式不符</li>
                    </ol>
                  </blockquote>
                  <h2 id="维护者信息-非必须"><a href="#维护者信息-非必须" class="headerlink" title="维护者信息(非必须)"></a>维护者信息(非必须)</h2>
                  <h3 id="MAINTAINER"><a href="#MAINTAINER" class="headerlink" title="MAINTAINER"></a>MAINTAINER</h3>
                  <figure class="highlight applescript">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="comment"># 格式</span></span><br><span class="line">MAINTAINR &lt;<span class="built_in">name</span>&gt;</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <h2 id="镜像操作指令-按需择选"><a href="#镜像操作指令-按需择选" class="headerlink" title="镜像操作指令(按需择选)"></a>镜像操作指令(按需择选)</h2>
                  <h3 id="COPY"><a href="#COPY" class="headerlink" title="COPY"></a>COPY</h3>
                  <blockquote>
                    <p>作用： 复制文件指令，从上下文 目录中复制或目录， 到容器中的指定路径 同等需求下建议使用COPY</p>
                  </blockquote>
                  <figure class="highlight xml">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"># 格式</span><br><span class="line">COPY <span class="tag">&lt;<span class="name">src</span>&gt;</span> <span class="tag">&lt;<span class="name">dest</span>&gt;</span></span><br><span class="line">COPY [--chown=<span class="tag">&lt;<span class="name">user</span>&gt;</span>:<span class="tag">&lt;<span class="name">group</span>&gt;</span>] <span class="tag">&lt;<span class="name">源路径1</span>&gt;</span>...  <span class="tag">&lt;<span class="name">目标路径</span>&gt;</span></span><br><span class="line">COPY [--chown=<span class="tag">&lt;<span class="name">user</span>&gt;</span>:<span class="tag">&lt;<span class="name">group</span>&gt;</span>] ["<span class="tag">&lt;<span class="name">源路径1</span>&gt;</span>",...  "<span class="tag">&lt;<span class="name">目标路径</span>&gt;</span>"]</span><br><span class="line"># [--chown=<span class="tag">&lt;<span class="name">user</span>&gt;</span>:<span class="tag">&lt;<span class="name">group</span>&gt;</span>]：可选参数，用户改变复制到容器内文件的拥有者和属组。</span><br><span class="line"># 复制本地主机的 `<span class="tag">&lt;<span class="name">src</span>&gt;</span>`（为 Dockerfile 所在目录的相对路径）到容器中的 `<span class="tag">&lt;<span class="name">dest</span>&gt;</span>`</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <blockquote>
                    <p><strong>&lt;源路径&gt;</strong>：源文件或者源目录，这里可以是通配符表达式，其通配符规则要满足 Go 的 filepath.Match 规则。</p>
                    <figure class="highlight dockerfile">
                      <table>
                        <tr>
                          <td class="gutter">
                            <pre><span class="line">1</span><br><span class="line">2</span><br></pre>
                          </td>
                          <td class="code">
                            <pre><span class="line"><span class="keyword">COPY</span><span class="bash"> hom* dir/</span></span><br><span class="line"><span class="keyword">COPY</span><span class="bash"> hom?.txt dir/</span></span><br></pre>
                          </td>
                        </tr>
                      </table>
                    </figure>
                    <p><strong>&lt;目标路径&gt;</strong>：容器内的指定路径，该路径不用事先建好，路径不存在的话，会自动创建。</p>
                  </blockquote>
                  <h3 id="ADD"><a href="#ADD" class="headerlink" title="ADD"></a>ADD</h3>
                  <blockquote>
                    <p>作用： 复制文件指令，从上下文 目录中复制或目录， 到容器中的指定路径 同等需求下建议使用COPY</p>
                  </blockquote>
                  <figure class="highlight autohotkey">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"># 格式 </span><br><span class="line">ADD &lt;src&gt; &lt;dest&gt;`</span><br><span class="line"></span><br><span class="line"># 该命令将复制指定的 `&lt;src&gt;` 到容器中的 `&lt;dest&gt;`。 </span><br><span class="line"># 其中 `&lt;src&gt;` 可以是Dockerfile所在目录的一个相对路径；也可以是一个 URL；还可以是一个 tar 文件（自动解压为目录）。</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <blockquote>
                    <ul>
                      <li>ADD 的优点：在执行 &lt;源文件&gt; 为 tar 压缩文件的话，压缩格式为 gzip, bzip2 以及 xz 的情况下，会自动复制并解压到 &lt;目标路径&gt;。</li>
                      <li>ADD 的缺点：在不解压的前提下，无法复制 tar 压缩文件。会令镜像构建缓存失效，从而可能会令镜像构建变得比较缓慢。具体是否使用，可以根据是否需要自动解压来决定</li>
                    </ul>
                  </blockquote>
                  <p>小结：</p>
                  <ul>
                    <li>ADD 与 COPY 功能无明显差异， 但针对性不同</li>
                    <li>当使用本地文件为源目录时，建议使用Copy</li>
                    <li>当需使用压缩包中文件时构建时，建议使用Copy</li>
                  </ul>
                  <h3 id="RUN"><a href="#RUN" class="headerlink" title="RUN"></a>RUN</h3>
                  <blockquote>
                    <p>作用: 用于在容器内执行命令</p>
                  </blockquote>
                  <figure class="highlight dockerfile">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="comment"># 格式</span></span><br><span class="line"><span class="keyword">RUN</span><span class="bash"> &lt;<span class="built_in">command</span>&gt; [option] <span class="comment"># 相当于shell格式</span></span></span><br><span class="line"><span class="keyword">RUN</span><span class="bash"> [<span class="string">"command"</span>, <span class="string">"option1"</span>, <span class="string">'option2'</span>] <span class="comment"># 相当于 exec 格式</span></span></span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <h3 id="WORKDIR"><a href="#WORKDIR" class="headerlink" title="WORKDIR"></a>WORKDIR</h3>
                  <blockquote>
                    <p>作用：指定工作目录。用 WORKDIR 指定的工作目录，会在构建镜像的每一层中都存在。（WORKDIR 指定的工作(主)目录，必须是提前创建好）。 docker build 构建镜像过程中的，每一个 RUN 命令都是新建的一层。只有通过 WORKDIR 创建的目录才会一直存在。</p>
                  </blockquote>
                  <figure class="highlight dockerfile">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="comment"># 格式</span></span><br><span class="line"><span class="keyword">WORKDIR</span><span class="bash">　&lt;dir&gt;</span></span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <h3 id="USE"><a href="#USE" class="headerlink" title="USE"></a>USE</h3>
                  <blockquote>
                    <p>作用:用于指定将使用命令的用户和用户组 此处只是切换后续命令执行的用户（用户和用户组必须提前已经存在）。 由于docker 无设置,默认需在root权限下运行 正所谓权限越大能力越大,若被入侵则造成损失较于其他权限为最大 安全与灵活性 二者相对斟酌</p>
                  </blockquote>
                  <figure class="highlight routeros">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="comment"># 格式</span></span><br><span class="line">USER &lt;username&gt;[:&lt;usergroup&gt;]</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <h3 id="EXPOSE"><a href="#EXPOSE" class="headerlink" title="EXPOSE"></a>EXPOSE</h3>
                  <blockquote>
                    <p>作用:仅声明端口</p>
                    <ul>
                      <li>方便配置映射</li>
                      <li>在运行时使用随机端口映射时，也就是 docker run -P 时，会自动随机映射 EXPOSE 的端口。</li>
                    </ul>
                  </blockquote>
                  <figure class="highlight dts">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="meta"># 格式</span></span><br><span class="line">EXPORT <span class="params">&lt;port1&gt;</span> [<span class="params">&lt;prot2&gt;</span> <span class="params">&lt;prot3&gt;</span> ...]</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <h2 id="执行指令"><a href="#执行指令" class="headerlink" title="执行指令"></a>执行指令</h2>
                  <h3 id="CMD"><a href="#CMD" class="headerlink" title="CMD"></a>CMD</h3>
                  <blockquote>
                    <p>作用: 类似于 RUN命令,但运行处不同</p>
                    <ul>
                      <li>RUN 在Docker build 前运行</li>
                      <li>CMD 在docker run 后运行</li>
                    </ul>
                    <p>注意:</p>
                    <ul>
                      <li>当 Dockerfile 中存在多个 CMD 指令，<strong>仅最后一个生效。</strong></li>
                      <li>CMD 指令指定的程序可被 docker run 命令行参数中指定要运行的程序所覆盖。</li>
                    </ul>
                    <p>当使用自定制镜像时,大致流程为</p>
                    <ul>
                      <li>编写业务代码</li>
                      <li>构建定制镜像(docker build)</li>
                      <li>docker 中运行业务 (Docker run)</li>
                    </ul>
                  </blockquote>
                  <figure class="highlight dockerfile">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="comment"># 格式</span></span><br><span class="line"><span class="keyword">CMD</span><span class="bash"> &lt;ShellCommand1 [option]&gt; [&amp;&amp;ShellCommand2[option] ]</span></span><br><span class="line"><span class="keyword">CMD</span><span class="bash"> [<span class="string">"&lt;可执行命令或文件&gt;"</span>, <span class="string">"&lt;option1&gt;"</span>, <span class="string">"&lt;option2&gt;"</span>, ... ]</span></span><br><span class="line"><span class="comment"># 此写法为保留字 ENTRYPOINT 指令指定的程序提供默认参数</span></span><br><span class="line"><span class="keyword">CMD</span><span class="bash"> [<span class="string">"&lt;command1&gt;"</span>, <span class="string">"&lt;command2&gt;"</span>, <span class="string">"&lt;command3&gt;"</span>, ...]</span></span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <h3 id="ENTRYPOINT"><a href="#ENTRYPOINT" class="headerlink" title="ENTRYPOINT"></a>ENTRYPOINT</h3>
                  <blockquote>
                    <p>作用: 功能与CMD相似,但不会被docker run 后的指定参数所覆盖, 命令行参数会被当作参数送给 ENTRYPOINT 指令指定的程序。 但是当docker run 使用了 —entrypoint 选项此选项的参数,可当作要运行的程序覆盖 ENTRYPOINT 指令指定的程序。 ENTRYPOINT CMD对比 同: 多个 指令，<strong>仅最后一个生效。</strong> 异: ENTRYPOINT选项的参数可当作要运行的程序覆盖 ENTRYPOINT 指令指定的程序。</p>
                  </blockquote>
                  <figure class="highlight dockerfile">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="comment"># 格式</span></span><br><span class="line"><span class="keyword">ENTRYPOINT</span><span class="bash"> [<span class="string">"&lt;可执行命令或文件&gt;"</span>,<span class="string">"option1"</span>, <span class="string">"option2"</span>]</span></span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <h3 id="ENV"><a href="#ENV" class="headerlink" title="ENV"></a>ENV</h3>
                  <blockquote>
                    <p>作用：配置容器内的环境变量，且保存，可以被后续 指令使用</p>
                  </blockquote>
                  <figure class="highlight dts">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="meta"># 格式</span></span><br><span class="line">ENV <span class="params">&lt;Key&gt;</span> <span class="params">&lt;Values&gt;</span></span><br><span class="line">ENV <span class="params">&lt;Key1&gt;</span>=<span class="params">&lt;Values1&gt;</span>, <span class="params">&lt;Key2&gt;</span>=<span class="params">&lt;Values2&gt;</span> ...</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <h3 id="ARG"><a href="#ARG" class="headerlink" title="ARG"></a>ARG</h3>
                  <blockquote>
                    <p>作用：配置容器内的环境变量，且保存，可以被后续 指令使用（与ENV功能相似） 不同：作用域不一样。ARG 设置的环境变量仅对 Dockerfile 内有效 也就是说只有 docker build 的过程中有效，构建好的镜像内不存在此环境变量。</p>
                    <figure class="highlight armasm">
                      <table>
                        <tr>
                          <td class="gutter">
                            <pre><span class="line">1</span><br></pre>
                          </td>
                          <td class="code">
                            <pre><span class="line">构建命令 docker <span class="keyword">build </span>中可以用 --<span class="keyword">build-arg </span>&lt;参数名&gt;=&lt;值&gt; 来覆盖。</span><br></pre>
                          </td>
                        </tr>
                      </table>
                    </figure>
                  </blockquote>
                  <figure class="highlight dts">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="meta"># 格式</span></span><br><span class="line">ARG <span class="params">&lt;key&gt;</span>[=默认值], <span class="params">&lt;Value&gt;</span></span><br><span class="line"><span class="meta"># 若不写Value 则Build时为自己写的默认值</span></span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <h3 id="VOLUME"><a href="#VOLUME" class="headerlink" title="VOLUME"></a>VOLUME</h3>
                  <blockquote>
                    <p>作用：定义匿名数据卷。在启动容器时忘记挂载数据卷，会自动挂载到匿名卷。</p>
                    <ul>
                      <li>避免重要的数据，因容器重启而丢失</li>
                      <li>避免容器不断变大</li>
                    </ul>
                  </blockquote>
                  <figure class="highlight dockerfile">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="comment"># 格式：</span></span><br><span class="line"><span class="keyword">VOLUME</span><span class="bash"> [<span class="string">"&lt;路径1&gt;"</span>, <span class="string">"&lt;路径2&gt;"</span>...]</span></span><br><span class="line"><span class="keyword">VOLUME</span><span class="bash"> &lt;路径&gt;</span></span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>在启动容器 docker run 的时候，我们可以通过 -v 参数修改挂载点。</p>
                  <h3 id="HEALTHCHECK"><a href="#HEALTHCHECK" class="headerlink" title="HEALTHCHECK"></a>HEALTHCHECK</h3>
                  <blockquote>
                    <p>作用: 用于指定某个程序或者指令来监控 docker 容器服务的运行状态。</p>
                  </blockquote>
                  <p>格式：</p>
                  <figure class="highlight dockerfile">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="keyword">HEALTHCHECK</span><span class="bash"> [option] CMD &lt;<span class="built_in">command</span>&gt; <span class="comment">#设置检查容器健康状况的命令</span></span></span><br><span class="line"><span class="keyword">HEALTHCHECK</span><span class="bash"> NONE <span class="comment"># 如果基础镜像有健康检查指令，使用这行可以屏蔽掉其健康检查指令</span></span></span><br><span class="line"><span class="keyword">HEALTHCHECK</span><span class="bash"> [option] CMD &lt;<span class="built_in">command</span>&gt; <span class="comment"># CMD 后面跟随的命令使用</span></span></span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <h3 id="ONBUILD"><a href="#ONBUILD" class="headerlink" title="ONBUILD"></a>ONBUILD</h3>
                  <blockquote>
                    <p>作用: 用于延迟构建命令的执行。 先构建一个父类镜像(ONBUILD 在父类中,但不立即执行),后子类继承此父类镜像(执行父类的ONBUILD 命令) 本次并不执行,当镜像调用它时,将执行父类中ONBUILD命令</p>
                  </blockquote>
                  <figure class="highlight dockerfile">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="comment"># 格式</span></span><br><span class="line"><span class="keyword">ONBUILD</span> &lt;其它指令&gt;</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  </p>
                </div>
              </div>
              <div class="post-meta">
                <span class="post-meta-item">
                  <span class="post-meta-item-icon">
                    <i class="far fa-user"></i>
                  </span>
                  <span class="post-meta-item-text">作者</span>
                  <span><a href="/authors/Payne" class="author" itemprop="url" rel="index">Payne</a></span>
                </span>
                <span class="post-meta-item">
                  <span class="post-meta-item-icon">
                    <i class="far fa-calendar"></i>
                  </span>
                  <span class="post-meta-item-text">发表于</span>
                  <time title="创建时间：2020-10-01 12:50:54" itemprop="dateCreated datePublished" datetime="2020-10-01T12:50:54+08:00">2020-10-01</time>
                </span>
                <span id="/10208.html" class="post-meta-item leancloud_visitors" data-flag-title="DockerFile" title="阅读次数">
                  <span class="post-meta-item-icon">
                    <i class="fa fa-eye"></i>
                  </span>
                  <span class="post-meta-item-text">阅读次数：</span>
                  <span class="leancloud-visitors-count"></span>
                </span>
                <span class="post-meta-item" title="本文字数">
                  <span class="post-meta-item-icon">
                    <i class="far fa-file-word"></i>
                  </span>
                  <span class="post-meta-item-text">本文字数：</span>
                  <span>4.5k</span>
                </span>
                <span class="post-meta-item" title="阅读时长">
                  <span class="post-meta-item-icon">
                    <i class="far fa-clock"></i>
                  </span>
                  <span class="post-meta-item-text">阅读时长 &asymp;</span>
                  <span>4 分钟</span>
                </span>
              </div>
            </article>
            <article itemscope itemtype="http://schema.org/Article" class="post-block index" lang="zh-CN">
              <link itemprop="mainEntityOfPage" href="https://cuiqingcai.com/10207.html">
              <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
                <meta itemprop="image" content="/images/avatar.png">
                <meta itemprop="name" content="崔庆才">
                <meta itemprop="description" content="崔庆才的个人站点，记录生活的瞬间，分享学习的心得。">
              </span>
              <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
                <meta itemprop="name" content="静觅">
              </span>
              <header class="post-header">
                <h2 class="post-title" itemprop="name headline">
                  <a class="label"> 技术杂谈 <i class="label-arrow"></i>
                  </a>
                  <a href="/10207.html" class="post-title-link" itemprop="url">Docker容器数据卷</a>
                </h2>
              </header>
              <div class="post-body" itemprop="articleBody">
                <div class="thumb">
                  <img itemprop="contentUrl" class="random">
                </div>
                <div class="excerpt">
                  <p>
                  <h1 id="Docker容器数据卷"><a href="#Docker容器数据卷" class="headerlink" title="Docker容器数据卷"></a>Docker容器数据卷</h1>
                  <h2 id="Docker理念："><a href="#Docker理念：" class="headerlink" title="Docker理念："></a>Docker理念：</h2>
                  <ul>
                    <li>将运用与运行的环境打包形成容器运行，运行可以伴随着容器，但由于对数据要求希望是持久化的</li>
                    <li>容器之间希望可以共享数据</li>
                  </ul>
                  <h2 id="一、Docker容器数据卷是什么？"><a href="#一、Docker容器数据卷是什么？" class="headerlink" title="一、Docker容器数据卷是什么？"></a>一、Docker容器数据卷是什么？</h2>
                  <ul>
                    <li>docker容器产生的数据，如果不通过docker commit生成新的镜像，使数据做为镜像的一部分保存下来，那么删除容器之后，数据也随之被删除。为了能保存数据在docker中，我们使用容器卷。</li>
                    <li>好比从电脑（docker）中拷贝数据（使用的U盘-容器卷）</li>
                  </ul>
                  <h2 id="二、Docker容器数据卷能干什么？"><a href="#二、Docker容器数据卷能干什么？" class="headerlink" title="二、Docker容器数据卷能干什么？"></a>二、Docker容器数据卷能干什么？</h2>
                  <ul>
                    <li>数据的持久化</li>
                    <li>容器间继承+共享数据</li>
                  </ul>
                  <h2 id="特点："><a href="#特点：" class="headerlink" title="特点："></a>特点：</h2>
                  <ul>
                    <li>容器之间共享过重用数据</li>
                    <li>卷中更改可之间生效</li>
                    <li>数据卷中的更改不会在镜像的更新中</li>
                    <li>数据中的更改不会包含在镜像的更新中</li>
                    <li>数据卷的生命周期一直持续到没有容器使用止</li>
                  </ul>
                  <h2 id="三、Docker容器数据卷"><a href="#三、Docker容器数据卷" class="headerlink" title="三、Docker容器数据卷"></a>三、Docker容器数据卷</h2>
                  <h2 id="容器内添加："><a href="#容器内添加：" class="headerlink" title="容器内添加："></a>容器内添加：</h2>
                  <figure class="highlight applescript">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line">docker <span class="built_in">run</span> -<span class="keyword">it</span> -v /[宿主机绝对路径目录]:[/容器内目录] [container_ID]</span><br><span class="line">docker <span class="built_in">run</span> -<span class="keyword">it</span> -v /myDataVolume:/dataVolumeContainer [镜像名]</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>权限报错处理：</p>
                  <figure class="highlight routeros">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line">docker <span class="builtin-name">run</span> -it -v /myDataVolume:/dataVolumeContainer <span class="attribute">--privileged</span>=<span class="literal">true</span> [镜像名]</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>检测是否数据卷是否挂载成功</p>
                  <figure class="highlight apache">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="attribute">docker</span> inspect<span class="meta"> [container_ID]</span></span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p><img src="https://qiniu.cuiqingcai.com/wp-content/uploads/2020/10/docker数据卷共享.png" alt=""> <img src="https://qiniu.cuiqingcai.com/wp-content/uploads/2020/10/容器状态.png" alt=""> 容器停止后，主机修改后数据是否同步 可以！但需为同一个容器！！！[The same container_id]</p>
                  <figure class="highlight properties">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="meta">使用docker</span> <span class="string">ps -l 查看运行过的容器信息</span></span><br><span class="line"><span class="comment"># 查看运行容器信息</span></span><br><span class="line"><span class="attr">docker</span> <span class="string">ps -l</span></span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <blockquote>
                    <p>命令(带权限):容器中只读，不可修改 docker run -it -v /宿主机绝对路径:/容器内目录:ro 镜像名</p>
                  </blockquote>
                  <h3 id="dockerfile-添加"><a href="#dockerfile-添加" class="headerlink" title="dockerfile 添加"></a>dockerfile 添加</h3>
                  <blockquote>
                    <p>javaEE:hello.java —-&gt; hello.class Docker: images ===》 DockerFile</p>
                  </blockquote>
                  <ol>
                    <li>新建mydocker文件夹并进入</li>
                    <li>在dockerfile中使用volume指令来给镜像添加一个或多个数据卷<ul>
                        <li>volume[“/dataVolumeContainer”,”/dataVolumeContainer2”,”/dataVolumeContainer3”]</li>
                      </ul>
                    </li>
                    <li>
                      <p>File构建</p>
                      <figure class="highlight dockerfile">
                        <table>
                          <tr>
                            <td class="gutter">
                              <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre>
                            </td>
                            <td class="code">
                              <pre><span class="line"><span class="comment"># volume test</span></span><br><span class="line"><span class="keyword">FROM</span> centos</span><br><span class="line"><span class="keyword">VOLUME</span><span class="bash"> [<span class="string">"/dataVolumeContainer1"</span>,<span class="string">"/dataVolumeContaine2"</span>]</span></span><br><span class="line"><span class="keyword">CMD</span><span class="bash"> <span class="built_in">echo</span> <span class="string">"finished,----sucess1"</span></span></span><br><span class="line"><span class="keyword">CMD</span><span class="bash"> /bin/bash</span></span><br></pre>
                            </td>
                          </tr>
                        </table>
                      </figure>
                    </li>
                    <li>
                      <p>build后生成镜像</p>
                      <figure class="highlight applescript">
                        <table>
                          <tr>
                            <td class="gutter">
                              <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre>
                            </td>
                            <td class="code">
                              <pre><span class="line">docker build -f /路径/文件名 -t 容器名：TAG . </span><br><span class="line">-f: <span class="built_in">file</span><span class="comment">--&gt;指定为文件</span></span><br><span class="line">-t：为容器重新分配一个为输入终端；</span><br><span class="line">. : 分布执行<span class="built_in">file</span>中命令</span><br></pre>
                            </td>
                          </tr>
                        </table>
                      </figure>
                    </li>
                  </ol>
                  <h2 id="四、Docker容器数据卷容器"><a href="#四、Docker容器数据卷容器" class="headerlink" title="四、Docker容器数据卷容器"></a>四、Docker容器数据卷容器</h2>
                  <p>命名的容器挂载数据卷，其他容器通过挂载这个(父容器)实现数据共享，挂载数据卷的容器称之为数据卷容器 容器间传递共享(volumes-from) <img src="https://qiniu.cuiqingcai.com/wp-content/uploads/2020/10/docker数据卷共享.png" alt=""></p>
                  <blockquote>
                    <p>dc01(主) 删除后 dc02(子1) dc03(子2)不受影响，dc02与dc3 继续传输</p>
                  </blockquote>
                  <p>结论：容器之间配置信息的传递，数据卷的生命周期一直持续到没有容器使用为止</p>
                  </p>
                </div>
              </div>
              <div class="post-meta">
                <span class="post-meta-item">
                  <span class="post-meta-item-icon">
                    <i class="far fa-user"></i>
                  </span>
                  <span class="post-meta-item-text">作者</span>
                  <span><a href="/authors/Payne" class="author" itemprop="url" rel="index">Payne</a></span>
                </span>
                <span class="post-meta-item">
                  <span class="post-meta-item-icon">
                    <i class="far fa-calendar"></i>
                  </span>
                  <span class="post-meta-item-text">发表于</span>
                  <time title="创建时间：2020-10-01 12:48:08" itemprop="dateCreated datePublished" datetime="2020-10-01T12:48:08+08:00">2020-10-01</time>
                </span>
                <span id="/10207.html" class="post-meta-item leancloud_visitors" data-flag-title="Docker容器数据卷" title="阅读次数">
                  <span class="post-meta-item-icon">
                    <i class="fa fa-eye"></i>
                  </span>
                  <span class="post-meta-item-text">阅读次数：</span>
                  <span class="leancloud-visitors-count"></span>
                </span>
                <span class="post-meta-item" title="本文字数">
                  <span class="post-meta-item-icon">
                    <i class="far fa-file-word"></i>
                  </span>
                  <span class="post-meta-item-text">本文字数：</span>
                  <span>1.3k</span>
                </span>
                <span class="post-meta-item" title="阅读时长">
                  <span class="post-meta-item-icon">
                    <i class="far fa-clock"></i>
                  </span>
                  <span class="post-meta-item-text">阅读时长 &asymp;</span>
                  <span>1 分钟</span>
                </span>
              </div>
            </article>
            <article itemscope itemtype="http://schema.org/Article" class="post-block index" lang="zh-CN">
              <link itemprop="mainEntityOfPage" href="https://cuiqingcai.com/10167.html">
              <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
                <meta itemprop="image" content="/images/avatar.png">
                <meta itemprop="name" content="崔庆才">
                <meta itemprop="description" content="崔庆才的个人站点，记录生活的瞬间，分享学习的心得。">
              </span>
              <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
                <meta itemprop="name" content="静觅">
              </span>
              <header class="post-header">
                <h2 class="post-title" itemprop="name headline">
                  <a class="label"> 技术杂谈 <i class="label-arrow"></i>
                  </a>
                  <a href="/10167.html" class="post-title-link" itemprop="url">手摸手搭建个人Leanote云笔记</a>
                </h2>
              </header>
              <div class="post-body" itemprop="articleBody">
                <div class="thumb">
                  <img itemprop="contentUrl" class="random">
                </div>
                <div class="excerpt">
                  <p>
                  <h1 id="搭建个人Leanote云笔记"><a href="#搭建个人Leanote云笔记" class="headerlink" title="搭建个人Leanote云笔记"></a>搭建个人Leanote云笔记</h1>
                  <blockquote>
                    <p>Leanote是一款在线的云笔记应用，有如下特点：</p>
                    <ul>
                      <li>支持网页、PC、手机APP客户端和微信版，随时记录，方便分享，支持语音，图片输入。</li>
                      <li>代码高亮，涵盖所有主流语言的代码高亮，随心所欲在Leanote里写代码，记知识。</li>
                      <li>Markdown 编辑器,实时同步预览。</li>
                      <li>专业数学公式编辑,像Word和Latex能编辑数学公式。</li>
                      <li>支持创建思维脑图，将散乱的想法以树状信息分层展示。</li>
                      <li>详细历史纪录，每次保存都在后端备份，轻松查找，一键恢复。</li>
                      <li>实时同步云端。</li>
                    </ul>
                  </blockquote>
                  <h2 id="简介"><a href="#简介" class="headerlink" title="简介"></a>简介</h2>
                  <p>基于Linux + Mongo + Leanote 快速搭建个人云笔记</p>
                  <h2 id="安装MongoDB"><a href="#安装MongoDB" class="headerlink" title="安装MongoDB"></a>安装MongoDB</h2>
                  <blockquote>
                    <p>MongoDB是一个基于分布式文件存储的高性能数据库，介于关系数据库和非关系数据库之间，它支持的数据结构非常松散是类似于json和bson格式，因此可以存储比较复杂的数据类型。Mongo最大的特点是它支持的查询语言非常强大，其语法有点类似于面向对象的查询语言，几乎可以实现类似关系数据库单表查询的绝大部分功能，而且还支持对数据建立索引。 Leanote云笔记使用MongoDB作为后端数据库，按照以下步骤按照MongoDB数据库。</p>
                  </blockquote>
                  <figure class="highlight properties">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="comment"># install MongoDB</span></span><br><span class="line"><span class="attr">yum</span> <span class="string">-y install mongodb mongodb-server.x86_64 mariadb-devel.i686</span></span><br><span class="line"><span class="comment"># start MongoDB service </span></span><br><span class="line"><span class="attr">systemctl</span> <span class="string">start mongod</span></span><br><span class="line"><span class="comment"># Verify mongodb running state</span></span><br><span class="line"><span class="attr">systemctl</span> <span class="string">status mongod</span></span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <h2 id="安装Leanote"><a href="#安装Leanote" class="headerlink" title="安装Leanote"></a>安装Leanote</h2>
                  <figure class="highlight vala">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="meta"># Download Leanote installation package</span></span><br><span class="line">wget https:<span class="comment">//nchc.dl.sourceforge.net/project/leanote-bin/2.6.1/leanote-linux-amd64-v2.6.1.bin.tar.gz</span></span><br><span class="line"><span class="meta"># Unzip </span></span><br><span class="line">tar -zxvf leanote-linux-amd64-v2<span class="number">.6</span><span class="number">.1</span>.bin.tar.gz</span><br><span class="line"><span class="meta"># setting leanote</span></span><br><span class="line">vim leanote/conf/app.conf</span><br><span class="line"><span class="meta"># change app.secret</span></span><br><span class="line">app.secret = Self configuration</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <h2 id="配置服务"><a href="#配置服务" class="headerlink" title="配置服务"></a>配置服务</h2>
                  <blockquote>
                    <p>If the following message appears</p>
                    <blockquote>
                      <p>Failed global initialization: BadValue Invalid or no user locale set. Please ensure LANG and/or LC_*</p>
                    </blockquote>
                    <p>Please configure the environment variables as follows</p>
                    <figure class="highlight routeros">
                      <table>
                        <tr>
                          <td class="gutter">
                            <pre><span class="line">1</span><br></pre>
                          </td>
                          <td class="code">
                            <pre><span class="line"><span class="builtin-name">export</span> <span class="attribute">LC_ALL</span>=C</span><br></pre>
                          </td>
                        </tr>
                      </table>
                    </figure>
                  </blockquote>
                  <figure class="highlight dts">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="meta"># init MongoDB</span></span><br><span class="line">mongorestore -h localhost -d leanote --dir <span class="meta-keyword">/root/</span>leanote/mongodb_backup/leanote_install_data/</span><br><span class="line"><span class="meta"># Start service </span></span><br><span class="line">nohup bash <span class="meta-keyword">/root/</span>leanote<span class="meta-keyword">/bin/</span>run.sh &gt; <span class="meta-keyword">/root/</span>leanote/run.log <span class="number">2</span>&gt;<span class="variable">&amp;1</span></span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <h2 id="访问笔记"><a href="#访问笔记" class="headerlink" title="访问笔记"></a>访问笔记</h2>
                  <p>在浏览器中访问<strong>服务器弹性地址：端口（默认9000）</strong></p>
                  <figure class="highlight avrasm">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="meta"># 默认账号</span></span><br><span class="line"><span class="symbol">username:</span> admin</span><br><span class="line"><span class="symbol">password:</span> abc123</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  </p>
                </div>
              </div>
              <div class="post-meta">
                <span class="post-meta-item">
                  <span class="post-meta-item-icon">
                    <i class="far fa-user"></i>
                  </span>
                  <span class="post-meta-item-text">作者</span>
                  <span><a href="/authors/Payne" class="author" itemprop="url" rel="index">Payne</a></span>
                </span>
                <span class="post-meta-item">
                  <span class="post-meta-item-icon">
                    <i class="far fa-calendar"></i>
                  </span>
                  <span class="post-meta-item-text">发表于</span>
                  <time title="创建时间：2020-09-27 18:58:45" itemprop="dateCreated datePublished" datetime="2020-09-27T18:58:45+08:00">2020-09-27</time>
                </span>
                <span id="/10167.html" class="post-meta-item leancloud_visitors" data-flag-title="手摸手搭建个人Leanote云笔记" title="阅读次数">
                  <span class="post-meta-item-icon">
                    <i class="fa fa-eye"></i>
                  </span>
                  <span class="post-meta-item-text">阅读次数：</span>
                  <span class="leancloud-visitors-count"></span>
                </span>
                <span class="post-meta-item" title="本文字数">
                  <span class="post-meta-item-icon">
                    <i class="far fa-file-word"></i>
                  </span>
                  <span class="post-meta-item-text">本文字数：</span>
                  <span>1.4k</span>
                </span>
                <span class="post-meta-item" title="阅读时长">
                  <span class="post-meta-item-icon">
                    <i class="far fa-clock"></i>
                  </span>
                  <span class="post-meta-item-text">阅读时长 &asymp;</span>
                  <span>1 分钟</span>
                </span>
              </div>
            </article>
            <article itemscope itemtype="http://schema.org/Article" class="post-block index" lang="zh-CN">
              <link itemprop="mainEntityOfPage" href="https://cuiqingcai.com/10017.html">
              <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
                <meta itemprop="image" content="/images/avatar.png">
                <meta itemprop="name" content="崔庆才">
                <meta itemprop="description" content="崔庆才的个人站点，记录生活的瞬间，分享学习的心得。">
              </span>
              <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
                <meta itemprop="name" content="静觅">
              </span>
              <header class="post-header">
                <h2 class="post-title" itemprop="name headline">
                  <a class="label"> 技术杂谈 <i class="label-arrow"></i>
                  </a>
                  <a href="/10017.html" class="post-title-link" itemprop="url">详解循环、迭代、递归、分治(Leet Code 509 斐波那契数列)，实际运用</a>
                </h2>
              </header>
              <div class="post-body" itemprop="articleBody">
                <div class="thumb">
                  <img itemprop="contentUrl" class="random">
                </div>
                <div class="excerpt">
                  <p>
                  <h1 id="Multiple-solutions-of-Fibonacci-Python-or-Java"><a href="#Multiple-solutions-of-Fibonacci-Python-or-Java" class="headerlink" title="Multiple solutions of Fibonacci (Python or Java)"></a>Multiple solutions of Fibonacci (Python or Java)</h1>
                  <p>本章是用英文写的，作为或想成为一名优秀的攻城狮，习惯阅读英文文档将使你受益良多。例如更好的查看最新版的官方文档、与国外友人交流、等等 其实英文的生词也并不多,其中90％的英文都在代码里，当然这其中的精华也在代码里，代码相信大部分伙计还是都可以看懂.所以，请不要惊慌。对于English，让我们一起取克服它、习惯它、拥抱它。然后把它锤倒在地，相信你可以的。 GO， Go， GO 如果实在不行，各种页面翻译来一手。莫慌，这都是小场面，啥都不是事儿，好吧</p>
                  <h3 id="Violence-law-Top-down"><a href="#Violence-law-Top-down" class="headerlink" title="Violence law(Top-down)"></a>Violence law(Top-down)</h3>
                  <blockquote>
                    <p>It can be solved directly according to the known conditions (f (0) = 0, f (1) = 1 F(N) = F(N - 1) + F(N - 2), for N &gt; 1)</p>
                    <h4 id="Python-Code"><a href="#Python-Code" class="headerlink" title="Python Code"></a>Python Code</h4>
                  </blockquote>
                  <figure class="highlight ruby">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span>:</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">fib</span><span class="params">(<span class="keyword">self</span>, <span class="symbol">N:</span> int)</span></span> -&gt; <span class="symbol">int:</span></span><br><span class="line">        <span class="keyword">if</span> N == <span class="number">1</span> <span class="keyword">or</span> N == <span class="number">2</span>: <span class="keyword">return</span> N</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">self</span>.fib(N - <span class="number">1</span>) + <span class="keyword">self</span>.fib(N - <span class="number">2</span>)</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <h4 id="Java-Code"><a href="#Java-Code" class="headerlink" title="Java Code"></a>Java Code</h4>
                  <figure class="highlight angelscript">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="keyword">class</span> <span class="symbol">Solution</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="built_in">int</span> fib(<span class="built_in">int</span> N) &#123;</span><br><span class="line">        <span class="keyword">if</span> (N == <span class="number">1</span> || N == <span class="number">2</span>) <span class="keyword">return</span> <span class="number">1</span>;</span><br><span class="line">        <span class="keyword">return</span> fib(N - <span class="number">1</span>) + fib(N - <span class="number">2</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="symbol">Solution</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="built_in">int</span> fib(<span class="built_in">int</span> N) &#123;</span><br><span class="line">        <span class="keyword">return</span> N &lt; <span class="number">2</span> ? N : fib(N - <span class="number">1</span>) + fib(N - <span class="number">2</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <h3 id="Violence-law-add-cache-Pruning"><a href="#Violence-law-add-cache-Pruning" class="headerlink" title="Violence law add cache(Pruning)"></a>Violence law add cache(Pruning)</h3>
                  <blockquote>
                    <p>We know that if we don’t do any processing, we will repeat too many calculations, which is very bad The processing idea will avoid repeated calculation</p>
                    <h4 id="Python-Code-1"><a href="#Python-Code-1" class="headerlink" title="Python Code"></a>Python Code</h4>
                  </blockquote>
                  <figure class="highlight ruby">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution2</span>:</span></span><br><span class="line">    @functools.lru_cache()</span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">fib</span><span class="params">(<span class="keyword">self</span>, <span class="symbol">N:</span> int)</span></span> -&gt; <span class="symbol">int:</span></span><br><span class="line">        <span class="keyword">if</span> N &lt;= <span class="number">1</span>: <span class="keyword">return</span> N</span><br><span class="line">        <span class="symbol">else:</span> <span class="keyword">return</span> <span class="keyword">self</span>.fib(N - <span class="number">1</span>) + <span class="keyword">self</span>.fib(N - <span class="number">2</span>)</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <h4 id="Java-Code-1"><a href="#Java-Code-1" class="headerlink" title="Java Code"></a>Java Code</h4>
                  <figure class="highlight angelscript">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="keyword">class</span> <span class="symbol">Solution</span> &#123;</span><br><span class="line">    <span class="keyword">private</span> Integer[] cache = new Integer[<span class="number">31</span>];</span><br><span class="line">    <span class="keyword">public</span> <span class="built_in">int</span> fib(<span class="built_in">int</span> N) &#123;</span><br><span class="line">        <span class="keyword">if</span> (N &lt;= <span class="number">1</span>) <span class="keyword">return</span> N;</span><br><span class="line">        cache[<span class="number">0</span>] = <span class="number">0</span>;</span><br><span class="line">        cache[<span class="number">1</span>] = <span class="number">1</span>;</span><br><span class="line">        <span class="keyword">return</span> memoize(N);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">public</span> <span class="built_in">int</span> memoize(<span class="built_in">int</span> N) &#123;</span><br><span class="line">      <span class="keyword">if</span> (cache[N] != <span class="literal">null</span>) <span class="keyword">return</span> cache[N];</span><br><span class="line">      cache[N] = memoize(N<span class="number">-1</span>) + memoize(N<span class="number">-2</span>);</span><br><span class="line">      <span class="keyword">return</span> memoize(N);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <h3 id="Divide-and-conquer-solution"><a href="#Divide-and-conquer-solution" class="headerlink" title="Divide and conquer solution"></a>Divide and conquer solution</h3>
                  <blockquote>
                    <p>Recursion, iteration, divide and conquer, backtracking, they do not have a clear distinction Recursion：The core idea is to govern separately and unify the officials</p>
                  </blockquote>
                  <figure class="highlight excel">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line">class Soluti<span class="symbol">on:</span></span><br><span class="line">    def fib(self, <span class="symbol">N:</span> <span class="built_in">int</span>) -&gt; i<span class="symbol">nt:</span></span><br><span class="line">        memo = &#123;&#125;</span><br><span class="line">        <span class="built_in">if</span> <span class="built_in">N</span> &lt; <span class="symbol">2:</span> return <span class="built_in">N</span></span><br><span class="line">        <span class="built_in">if</span> <span class="built_in">N</span>-<span class="number">1</span> <span class="built_in">not</span> in me<span class="symbol">mo:</span> memo[<span class="built_in">N</span>-<span class="number">1</span>] = self.fib(<span class="built_in">N</span>-<span class="number">1</span>)</span><br><span class="line">        <span class="built_in">if</span> <span class="built_in">N</span>-<span class="number">2</span> <span class="built_in">not</span> in me<span class="symbol">mo:</span> memo[<span class="built_in">N</span>-<span class="number">2</span>] = self.fib(<span class="built_in">N</span>-<span class="number">2</span>)</span><br><span class="line">        return memo[<span class="built_in">N</span>-<span class="number">1</span>] + memo[<span class="built_in">N</span>-<span class="number">2</span>]</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <h3 id="Dynamic-recursion-Bottom-up"><a href="#Dynamic-recursion-Bottom-up" class="headerlink" title="Dynamic recursion(Bottom up)"></a>Dynamic recursion(Bottom up)</h3>
                  <h4 id="Basic-solutions"><a href="#Basic-solutions" class="headerlink" title="Basic solutions"></a>Basic solutions</h4>
                  <blockquote>
                    <p>More initial value, continuous dynamic recursive</p>
                  </blockquote>
                  <h5 id="Python-Code-2"><a href="#Python-Code-2" class="headerlink" title="Python Code"></a>Python Code</h5>
                  <figure class="highlight vim">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line">class Solution:</span><br><span class="line">    def fib(self, <span class="keyword">N</span>: <span class="keyword">int</span>) -&gt; in<span class="variable">t:</span></span><br><span class="line">        <span class="keyword">if</span> <span class="keyword">N</span> &lt; <span class="number">2</span>: <span class="keyword">return</span> <span class="keyword">N</span></span><br><span class="line">        <span class="keyword">dp</span> = [<span class="number">0</span> <span class="keyword">for</span> _ in <span class="built_in">range</span>(<span class="keyword">N</span> + <span class="number">1</span>)]</span><br><span class="line">        <span class="keyword">dp</span>[<span class="number">0</span>], <span class="keyword">dp</span>[<span class="number">1</span>] = <span class="number">0</span>, <span class="number">1</span></span><br><span class="line">        <span class="keyword">for</span> i in <span class="built_in">range</span>(<span class="number">2</span>, <span class="keyword">N</span> + <span class="number">1</span>):</span><br><span class="line">            <span class="keyword">dp</span>[i] = <span class="keyword">dp</span>[i - <span class="number">1</span>] + <span class="keyword">dp</span>[i - <span class="number">2</span>]</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">dp</span>[- <span class="number">1</span>]</span><br><span class="line"></span><br><span class="line">class Solution:</span><br><span class="line">    def fib(self, <span class="keyword">N</span>: <span class="keyword">int</span>) -&gt; in<span class="variable">t:</span></span><br><span class="line">        <span class="keyword">if</span> <span class="keyword">N</span> == <span class="number">0</span>: <span class="keyword">return</span> <span class="number">0</span></span><br><span class="line">        memo = [<span class="number">0</span>,<span class="number">1</span>]</span><br><span class="line">        <span class="keyword">for</span> _ in <span class="built_in">range</span>(<span class="number">2</span>,<span class="keyword">N</span>+<span class="number">1</span>):</span><br><span class="line">            memo = [memo[-<span class="number">1</span>], memo[-<span class="number">1</span>] + memo[-<span class="number">2</span>]]</span><br><span class="line">        <span class="keyword">return</span> memo[-<span class="number">1</span>]</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <h5 id="Java-Code-2"><a href="#Java-Code-2" class="headerlink" title="Java Code"></a>Java Code</h5>
                  <figure class="highlight angelscript">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="keyword">class</span> <span class="symbol">Solution</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="built_in">int</span> fib(<span class="built_in">int</span> N) &#123;</span><br><span class="line">        <span class="keyword">if</span> (N &lt;= <span class="number">1</span>) <span class="keyword">return</span> N;</span><br><span class="line">        <span class="keyword">if</span> (N == <span class="number">2</span>) <span class="keyword">return</span> <span class="number">1</span>;</span><br><span class="line">        <span class="built_in">int</span> curr = <span class="number">0</span>, prev1 = <span class="number">1</span>, prev2 = <span class="number">1</span>;</span><br><span class="line">        <span class="keyword">for</span> (<span class="built_in">int</span> i = <span class="number">3</span>; i &lt;= N; i++) &#123;</span><br><span class="line">            curr = prev1 + prev2;</span><br><span class="line">            prev2 = prev1;</span><br><span class="line">            prev1 = curr;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> curr;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <h4 id="Use-better-base-types-tuples-to-improve-performance"><a href="#Use-better-base-types-tuples-to-improve-performance" class="headerlink" title="Use better base types (tuples) to improve performance"></a>Use better base types (tuples) to improve performance</h4>
                  <figure class="highlight ruby">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span>:</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">fib</span><span class="params">(<span class="keyword">self</span>, <span class="symbol">N:</span> int)</span></span> -&gt; <span class="symbol">int:</span></span><br><span class="line">        <span class="keyword">if</span> N == <span class="number">0</span>: <span class="keyword">return</span> <span class="number">0</span></span><br><span class="line">        memo = (<span class="number">0</span>,<span class="number">1</span>)</span><br><span class="line">        <span class="keyword">for</span> <span class="number">_</span> <span class="keyword">in</span> range(<span class="number">2</span>,N+<span class="number">1</span>)<span class="symbol">:</span></span><br><span class="line">            memo = (memo[-<span class="number">1</span>], memo[-<span class="number">1</span>] + memo[-<span class="number">2</span>])</span><br><span class="line">        <span class="keyword">return</span> memo[-<span class="number">1</span>]</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <h3 id="Better-solutions"><a href="#Better-solutions" class="headerlink" title="Better solutions"></a>Better solutions</h3>
                  <h4 id="Python-Code-3"><a href="#Python-Code-3" class="headerlink" title="Python Code"></a>Python Code</h4>
                  <figure class="highlight ruby">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span>:</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">fib</span><span class="params">(<span class="keyword">self</span>, <span class="symbol">N:</span> int)</span></span> -&gt; <span class="symbol">int:</span></span><br><span class="line">        curr, prev1, prev2 = <span class="number">0</span>, <span class="number">1</span>, <span class="number">1</span></span><br><span class="line">        <span class="keyword">for</span> i <span class="keyword">in</span> range(<span class="number">3</span>, N + <span class="number">1</span>)<span class="symbol">:</span></span><br><span class="line">            curr = prev1 + prev2</span><br><span class="line">            prev2 = prev1</span><br><span class="line">            prev1 = curr</span><br><span class="line">        <span class="keyword">return</span> curr</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution5</span>:</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">fib</span><span class="params">(<span class="keyword">self</span>, <span class="symbol">N:</span> int)</span></span> -&gt; <span class="symbol">int:</span></span><br><span class="line">        prev, now = <span class="number">0</span>, <span class="number">1</span></span><br><span class="line">        <span class="keyword">for</span> i <span class="keyword">in</span> range(N)<span class="symbol">:</span></span><br><span class="line">            prev, now = now, now + prev</span><br><span class="line">        <span class="keyword">return</span> prev</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <h4 id="Java-Code-3"><a href="#Java-Code-3" class="headerlink" title="Java Code"></a>Java Code</h4>
                  <figure class="highlight angelscript">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="keyword">class</span> <span class="symbol">Solution</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="built_in">int</span> fib(<span class="built_in">int</span> N) &#123;</span><br><span class="line">    <span class="keyword">if</span> (N == <span class="number">0</span>) <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">if</span> (N == <span class="number">2</span> || N == <span class="number">1</span>) <span class="keyword">return</span> <span class="number">1</span>;</span><br><span class="line">    <span class="built_in">int</span> prev = <span class="number">1</span>, curr = <span class="number">1</span>;</span><br><span class="line">    <span class="keyword">for</span> (<span class="built_in">int</span> i = <span class="number">3</span>; i &lt;= N; i++) &#123;</span><br><span class="line">        <span class="built_in">int</span> sum = prev + curr;</span><br><span class="line">        prev = curr;</span><br><span class="line">        curr = sum;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> curr;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <h3 id="Mathematical-conclusion-method"><a href="#Mathematical-conclusion-method" class="headerlink" title="Mathematical conclusion method"></a>Mathematical conclusion method</h3>
                  <h4 id="Python-Code-4"><a href="#Python-Code-4" class="headerlink" title="Python Code"></a>Python Code</h4>
                  <figure class="highlight crystal">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span>:</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">fib</span></span>(<span class="keyword">self</span>, <span class="symbol">N:</span> int) -&gt; <span class="symbol">int:</span></span><br><span class="line">        sqrt5 = <span class="number">5</span> ** <span class="number">0.5</span></span><br><span class="line">        <span class="function"><span class="keyword">fun</span> = <span class="title">pow</span></span>((<span class="number">1</span> + sqrt5) / <span class="number">2</span>, n + <span class="number">1</span>) - pow((<span class="number">1</span> - sqrt5) / <span class="number">2</span>, n + <span class="number">1</span>)</span><br><span class="line">        <span class="keyword">return</span> int(<span class="function"><span class="keyword">fun</span> <span class="title">/</span></span> sqrt5)</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <h4 id="Java-Code-4"><a href="#Java-Code-4" class="headerlink" title="Java Code"></a>Java Code</h4>
                  <figure class="highlight angelscript">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="keyword">class</span> <span class="symbol">Solution</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="built_in">int</span> fib(<span class="built_in">int</span> N) &#123;</span><br><span class="line">        <span class="built_in">double</span> sqrt5 = (<span class="number">1</span> + Math.sqrt(<span class="number">5</span>)) / <span class="number">2</span>;</span><br><span class="line">        <span class="keyword">return</span> (<span class="built_in">int</span>)Math.round(Math.pow(sqrt5, N)/ Math.sqrt(<span class="number">5</span>));</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  </p>
                </div>
              </div>
              <div class="post-meta">
                <span class="post-meta-item">
                  <span class="post-meta-item-icon">
                    <i class="far fa-user"></i>
                  </span>
                  <span class="post-meta-item-text">作者</span>
                  <span><a href="/authors/Payne" class="author" itemprop="url" rel="index">Payne</a></span>
                </span>
                <span class="post-meta-item">
                  <span class="post-meta-item-icon">
                    <i class="far fa-calendar"></i>
                  </span>
                  <span class="post-meta-item-text">发表于</span>
                  <time title="创建时间：2020-09-23 00:49:49" itemprop="dateCreated datePublished" datetime="2020-09-23T00:49:49+08:00">2020-09-23</time>
                </span>
                <span id="/10017.html" class="post-meta-item leancloud_visitors" data-flag-title="详解循环、迭代、递归、分治(Leet Code 509 斐波那契数列)，实际运用" title="阅读次数">
                  <span class="post-meta-item-icon">
                    <i class="fa fa-eye"></i>
                  </span>
                  <span class="post-meta-item-text">阅读次数：</span>
                  <span class="leancloud-visitors-count"></span>
                </span>
                <span class="post-meta-item" title="本文字数">
                  <span class="post-meta-item-icon">
                    <i class="far fa-file-word"></i>
                  </span>
                  <span class="post-meta-item-text">本文字数：</span>
                  <span>3.2k</span>
                </span>
                <span class="post-meta-item" title="阅读时长">
                  <span class="post-meta-item-icon">
                    <i class="far fa-clock"></i>
                  </span>
                  <span class="post-meta-item-text">阅读时长 &asymp;</span>
                  <span>3 分钟</span>
                </span>
              </div>
            </article>
            <article itemscope itemtype="http://schema.org/Article" class="post-block index" lang="zh-CN">
              <link itemprop="mainEntityOfPage" href="https://cuiqingcai.com/10014.html">
              <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
                <meta itemprop="image" content="/images/avatar.png">
                <meta itemprop="name" content="崔庆才">
                <meta itemprop="description" content="崔庆才的个人站点，记录生活的瞬间，分享学习的心得。">
              </span>
              <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
                <meta itemprop="name" content="静觅">
              </span>
              <header class="post-header">
                <h2 class="post-title" itemprop="name headline">
                  <a class="label"> Other <i class="label-arrow"></i>
                  </a>
                  <a href="/10014.html" class="post-title-link" itemprop="url">追根揭底-循环、迭代、分治、回溯</a>
                </h2>
              </header>
              <div class="post-body" itemprop="articleBody">
                <div class="thumb">
                  <img itemprop="contentUrl" class="random">
                </div>
                <div class="excerpt">
                  <p>
                  <p>在计算机的世界中由最基本的for loop、while loop、if…else无限衍生，无论多么复杂的逻辑最后大多可归纳为以上三种。当然除非原本逻辑无重复性，无条件分支。</p>
                  <h2 id="一、循环-重复"><a href="#一、循环-重复" class="headerlink" title="一、循环(重复)"></a>一、循环(重复)</h2>
                  <p>不断的重复、有始有终 循环实现</p>
                  <figure class="highlight gcode">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line">private loop<span class="comment">()</span>&#123;</span><br><span class="line">    for<span class="comment">(start; end; loop termination)</span>&#123;</span><br><span class="line">        expressio<span class="symbol">n1</span>;</span><br><span class="line">        expressio<span class="symbol">n2</span>;</span><br><span class="line">        expressio<span class="symbol">n3</span>;        </span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <figure class="highlight ruby">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">loop</span><span class="params">()</span></span><span class="symbol">:</span></span><br><span class="line">    <span class="keyword">for</span> start <span class="keyword">in</span> <span class="keyword">end</span>/<span class="symbol">loop_termination:</span></span><br><span class="line">        expression1;</span><br><span class="line">        expression2;</span><br><span class="line">        expression3;</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <h2 id="二、递归"><a href="#二、递归" class="headerlink" title="二、递归"></a>二、递归</h2>
                  <hr>
                  <p>特征：自相似性、有始有终 实现：归去来兮、适可而止 何时想到递归？</p>
                  <blockquote>
                    <p>子问题与原始问题做同样的事</p>
                  </blockquote>
                  <p>递归实现：</p>
                  <figure class="highlight arduino">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="function"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title">recursion</span><span class="params">(<span class="keyword">int</span> level,<span class="keyword">int</span> param1,<span class="keyword">int</span> param2...)</span>:</span>&#123;</span><br><span class="line">    <span class="comment">// 终止条件(recursion terminato)</span></span><br><span class="line">    <span class="keyword">if</span>(level &gt; MAX_LEVEL)&#123;</span><br><span class="line">        # process_rsult</span><br><span class="line">        <span class="keyword">return</span></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">// 处理此层过程逻辑(process logic in current level)</span></span><br><span class="line">     <span class="built_in">process</span>(level, data1, data2...)</span><br><span class="line">    <span class="comment">// 进入下一层（dill down）</span></span><br><span class="line">    recursion(level: level + <span class="number">1</span>, newParam):</span><br><span class="line">    <span class="comment">// 如果需要恢复此层状态    </span></span><br><span class="line">&#125;</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <figure class="highlight powershell">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line">def recursion(level, <span class="keyword">param</span>1, <span class="keyword">param</span>2...):</span><br><span class="line">    <span class="comment"># 终止条件(recursion terminato)</span></span><br><span class="line">    <span class="keyword">if</span> level &gt; MAX_LEVEL:</span><br><span class="line">       <span class="comment"># process_rsult</span></span><br><span class="line">        <span class="keyword">return</span></span><br><span class="line">    <span class="comment"># 处理此层过程逻辑(process logic in current level)</span></span><br><span class="line">    <span class="keyword">process</span>(level, <span class="keyword">data</span>1, <span class="keyword">data</span>2...)</span><br><span class="line">    <span class="comment"># 进入下一层（dill down）</span></span><br><span class="line">    self.recursion(level + <span class="number">1</span>, <span class="keyword">param</span>1, <span class="keyword">param</span>2...):</span><br><span class="line">    <span class="comment"># 如果需要恢复此层状态</span></span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <h2 id="二、分治"><a href="#二、分治" class="headerlink" title="二、分治"></a>二、分治</h2>
                  <hr>
                  <p>定义：分而治之，群臣归一 何时想到分治？</p>
                  <blockquote>
                    <p>当复杂的问题可以拆分成简单的子问题</p>
                  </blockquote>
                  <p>分治实现：</p>
                  <figure class="highlight reasonml">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="keyword">private</span> static <span class="built_in">int</span> divide<span class="constructor">_conquer(Problem, Param1, Param2<span class="operator">...</span>)</span> &#123;</span><br><span class="line">  <span class="comment">// 终止条件</span></span><br><span class="line">  <span class="keyword">if</span> (problem<span class="operator"> == </span>NULL) &#123;</span><br><span class="line">    <span class="built_in">int</span> res = process<span class="constructor">_last_result()</span>;</span><br><span class="line">    return res;     </span><br><span class="line">  &#125;</span><br><span class="line">  <span class="comment">// 拆分子问题</span></span><br><span class="line">  subProblems = split<span class="constructor">_problem(<span class="params">problem</span>)</span></span><br><span class="line"></span><br><span class="line">  res0 = divide<span class="constructor">_conquer(<span class="params">subProblems</span>[0])</span></span><br><span class="line">  res1 = divide<span class="constructor">_conquer(<span class="params">subProblems</span>[1])</span></span><br><span class="line"><span class="operator">  ... </span></span><br><span class="line">  <span class="comment">// 合并子问题结果</span></span><br><span class="line">  result = process<span class="constructor">_result(<span class="params">res0</span>, <span class="params">res1</span>)</span>;</span><br><span class="line"></span><br><span class="line">  return result;</span><br><span class="line">&#125;</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <figure class="highlight reasonml">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line">def divide<span class="constructor">_conquer(Problem, Param1, Param2<span class="operator">...</span>)</span>:</span><br><span class="line">     # 终止条件</span><br><span class="line">     <span class="keyword">if</span> problem is None:</span><br><span class="line">        return </span><br><span class="line">     # 拆分子问题</span><br><span class="line">     subproblems = split<span class="constructor">_problem(<span class="params">problem</span>, <span class="params">data</span>)</span> </span><br><span class="line">     subresult1 = self.divide<span class="constructor">_conquer(<span class="params">subproblems</span>[0], <span class="params">p1</span>, <span class="operator">...</span>)</span> </span><br><span class="line">     subresult2 = self.divide<span class="constructor">_conquer(<span class="params">subproblems</span>[1], <span class="params">p1</span>, <span class="operator">...</span>)</span> </span><br><span class="line">     subresult3 = self.divide<span class="constructor">_conquer(<span class="params">subproblems</span>[2], <span class="params">p1</span>, <span class="operator">...</span>)</span> </span><br><span class="line">      ...</span><br><span class="line">     # 合并子问题结果</span><br><span class="line">     result = process<span class="constructor">_result(<span class="params">subresult1</span>, <span class="params">subresult2</span>, <span class="params">subresult3</span>, …)</span></span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <h2 id="三：回溯"><a href="#三：回溯" class="headerlink" title="三：回溯"></a>三：回溯</h2>
                  <hr>
                  <p>采用“试错”思想，尝试“分步”去解决问题。在分步的过程中。根据上层结果，尝试此层最优解决此问题，如果此层较于上层不是最优则回溯。</p>
                  <h2 id="四、DP-Dynamic-programming-动态规划-动态递推"><a href="#四、DP-Dynamic-programming-动态规划-动态递推" class="headerlink" title="四、DP(Dynamic programming) 动态规划/动态递推"></a>四、DP(<strong>Dynamic programming</strong>) 动态规划/动态递推</h2>
                  <hr>
                  <p>定义</p>
                  <blockquote>
                    <p>In both contexts it refers to simplifying a complicated problem by breaking it down into simpler sub-problems in a recursive manner. While some decision problems cannot be taken apart this way, decisions that span several points in time do often break apart recursively. 在这两种情况下，它都是指通过递归的方式将复杂问题分解为更简单的子问题来简化它。虽然有些决策问题不能用这种方式分解，但是跨越多个时间点的决策通常会递归地分解。 Simplifying a complicated problem by breaking it down into simpler sub problem(in a recursibe manner) 把一个复杂的问题分解成更简单的子问题简化它(用一种递归的方式)</p>
                  </blockquote>
                  <p>自低向上 动态规划关键点：</p>
                  <ul>
                    <li>最优子结构</li>
                    <li>储存中间状态</li>
                    <li>递推公式(状态转移方程，DP方程)</li>
                    <li>eg</li>
                  </ul>
                  <figure class="highlight markdown">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="section"># 一维</span></span><br><span class="line">Fib：</span><br><span class="line"><span class="code">    opt[i] = opt[n - 1] + opt[n - 2]</span></span><br><span class="line"><span class="section"># 二维</span></span><br><span class="line">  opt[<span class="string">i</span>][<span class="symbol">j</span>] = opt[<span class="string">i + 1</span>][<span class="symbol">j</span>] + opt[<span class="string">i</span>][<span class="symbol">j + 1</span>]</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>以斐波那契数列为例：</p>
                  <figure class="highlight angelscript">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line">F(<span class="number">0</span>) = <span class="number">0</span>, F(<span class="number">1</span>) = <span class="number">1</span> </span><br><span class="line"></span><br><span class="line">F（N） =  F（N　－　１）　＋ F（N　－　２）（N &gt;= <span class="number">2</span>）</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>递归(傻递归)： 若计算F(4)；需计算</p>
                  <figure class="highlight angelscript">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line">lin1 F(<span class="number">4</span>) = f（<span class="number">3</span>）、f（<span class="number">2</span>）， </span><br><span class="line">lin2 F(<span class="number">3</span>):f（<span class="number">2</span>）、f（<span class="number">1</span>）， F(<span class="number">2</span>) = f(<span class="number">1</span>) + f(<span class="number">0</span>)</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>DP：</p>
                  <figure class="highlight angelscript">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line">i(<span class="number">0</span>) = <span class="number">0</span>, i(<span class="number">1</span>) = <span class="number">1</span></span><br><span class="line">[<span class="number">0</span>, <span class="number">1</span>, <span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">5</span>]</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2>
                  <p>动态规划、递归、分治、无本质区别 共性： 重复子问题 异性：最优子结构、中途淘汰次优</p>
                  </p>
                </div>
              </div>
              <div class="post-meta">
                <span class="post-meta-item">
                  <span class="post-meta-item-icon">
                    <i class="far fa-user"></i>
                  </span>
                  <span class="post-meta-item-text">作者</span>
                  <span><a href="/authors/Payne" class="author" itemprop="url" rel="index">Payne</a></span>
                </span>
                <span class="post-meta-item">
                  <span class="post-meta-item-icon">
                    <i class="far fa-calendar"></i>
                  </span>
                  <span class="post-meta-item-text">发表于</span>
                  <time title="创建时间：2020-09-23 00:37:18" itemprop="dateCreated datePublished" datetime="2020-09-23T00:37:18+08:00">2020-09-23</time>
                </span>
                <span id="/10014.html" class="post-meta-item leancloud_visitors" data-flag-title="追根揭底-循环、迭代、分治、回溯" title="阅读次数">
                  <span class="post-meta-item-icon">
                    <i class="fa fa-eye"></i>
                  </span>
                  <span class="post-meta-item-text">阅读次数：</span>
                  <span class="leancloud-visitors-count"></span>
                </span>
                <span class="post-meta-item" title="本文字数">
                  <span class="post-meta-item-icon">
                    <i class="far fa-file-word"></i>
                  </span>
                  <span class="post-meta-item-text">本文字数：</span>
                  <span>2.5k</span>
                </span>
                <span class="post-meta-item" title="阅读时长">
                  <span class="post-meta-item-icon">
                    <i class="far fa-clock"></i>
                  </span>
                  <span class="post-meta-item-text">阅读时长 &asymp;</span>
                  <span>2 分钟</span>
                </span>
              </div>
            </article>
            <article itemscope itemtype="http://schema.org/Article" class="post-block index" lang="zh-CN">
              <link itemprop="mainEntityOfPage" href="https://cuiqingcai.com/9997.html">
              <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
                <meta itemprop="image" content="/images/avatar.png">
                <meta itemprop="name" content="崔庆才">
                <meta itemprop="description" content="崔庆才的个人站点，记录生活的瞬间，分享学习的心得。">
              </span>
              <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
                <meta itemprop="name" content="静觅">
              </span>
              <header class="post-header">
                <h2 class="post-title" itemprop="name headline">
                  <a class="label"> 技术杂谈 <i class="label-arrow"></i>
                  </a>
                  <a href="/9997.html" class="post-title-link" itemprop="url">Git 中文显示编码问题解决</a>
                </h2>
              </header>
              <div class="post-body" itemprop="articleBody">
                <div class="thumb">
                  <img itemprop="contentUrl" class="random">
                </div>
                <div class="excerpt">
                  <p>
                  <p>刚装了台新机器，Git 显示总是呈现这样的样子：</p>
                  <figure class="highlight taggerscript">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line">"<span class="symbol">\3</span>46<span class="symbol">\2</span>65<span class="symbol">\2</span>13<span class="symbol">\3</span>50<span class="symbol">\2</span>57<span class="symbol">\2</span>25.txt"</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>解决办法：</p>
                  <figure class="highlight routeros">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line">git<span class="built_in"> config </span>--global core.quotepath <span class="literal">false</span></span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>仅此记录，完毕。</p>
                  </p>
                </div>
              </div>
              <div class="post-meta">
                <span class="post-meta-item">
                  <span class="post-meta-item-icon">
                    <i class="far fa-user"></i>
                  </span>
                  <span class="post-meta-item-text">作者</span>
                  <span><a href="/authors/崔庆才" class="author" itemprop="url" rel="index">崔庆才</a></span>
                </span>
                <span class="post-meta-item">
                  <span class="post-meta-item-icon">
                    <i class="far fa-calendar"></i>
                  </span>
                  <span class="post-meta-item-text">发表于</span>
                  <time title="创建时间：2020-09-21 22:56:13" itemprop="dateCreated datePublished" datetime="2020-09-21T22:56:13+08:00">2020-09-21</time>
                </span>
                <span id="/9997.html" class="post-meta-item leancloud_visitors" data-flag-title="Git 中文显示编码问题解决" title="阅读次数">
                  <span class="post-meta-item-icon">
                    <i class="fa fa-eye"></i>
                  </span>
                  <span class="post-meta-item-text">阅读次数：</span>
                  <span class="leancloud-visitors-count"></span>
                </span>
                <span class="post-meta-item" title="本文字数">
                  <span class="post-meta-item-icon">
                    <i class="far fa-file-word"></i>
                  </span>
                  <span class="post-meta-item-text">本文字数：</span>
                  <span>104</span>
                </span>
                <span class="post-meta-item" title="阅读时长">
                  <span class="post-meta-item-icon">
                    <i class="far fa-clock"></i>
                  </span>
                  <span class="post-meta-item-text">阅读时长 &asymp;</span>
                  <span>1 分钟</span>
                </span>
              </div>
            </article>
            <article itemscope itemtype="http://schema.org/Article" class="post-block index" lang="zh-CN">
              <link itemprop="mainEntityOfPage" href="https://cuiqingcai.com/9640.html">
              <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
                <meta itemprop="image" content="/images/avatar.png">
                <meta itemprop="name" content="崔庆才">
                <meta itemprop="description" content="崔庆才的个人站点，记录生活的瞬间，分享学习的心得。">
              </span>
              <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
                <meta itemprop="name" content="静觅">
              </span>
              <header class="post-header">
                <h2 class="post-title" itemprop="name headline">
                  <a class="label"> 技术杂谈 <i class="label-arrow"></i>
                  </a>
                  <a href="/9640.html" class="post-title-link" itemprop="url">浅淡程序设计模式-总纲篇</a>
                </h2>
              </header>
              <div class="post-body" itemprop="articleBody">
                <div class="thumb">
                  <img itemprop="contentUrl" class="random">
                </div>
                <div class="excerpt">
                  <p>
                  <p>设计模式(Design Patterns),旨在软件设计（<strong><em>可重用的面向对象软件的要素</em></strong>）中，被反复使用的一种代码设计经验。设计模式旨在简化代码量、降低耦合度、高效使用可重用代码，提高代码可拓性和可维护性。</p>
                  <blockquote>
                    <p><strong>3V3H概念：</strong> 3V: Voluem(海量)，Variety(多样)、Velocity(实时) 3H: High concurrency(高并发)、High performance(高性能)、High development(高可拓)</p>
                  </blockquote>
                  <h2 id="设计模式的由来："><a href="#设计模式的由来：" class="headerlink" title="设计模式的由来："></a>设计模式的由来：</h2>
                  <p>设计模式这个术语是由上个世纪90年代Erich Gamma、Richard Helm、Raplh Johnson和Jonhn Vlissides四人总结提炼而出。并编写了<a href="https://en.wikipedia.org/wiki/Design_Patterns" target="_blank" rel="noopener">Design_Patterns</a>(设计模式)一书，他们四位统称为GOF(俗称四人帮)。 设计模式：即 将常使用的设计思想提炼出一个个模式，然后给每个模式命名，这样在使用的时候更方便交流。GOF把23个常用模式分为创建型模式、结构型模式和行为型模式三类</p>
                  <h2 id="为何采用设计模式思想？-请注意思想二词！！！"><a href="#为何采用设计模式思想？-请注意思想二词！！！" class="headerlink" title="为何采用设计模式思想？(请注意思想二词！！！)"></a>为何采用设计模式<strong>思想</strong>？(请注意思想二词！！！)</h2>
                  <blockquote>
                    <p>设计模式并非直接用来完成编码，而是描述在各种不同情况下，要怎么<strong>解决问题的一种方案</strong>、<strong>一种思想</strong> <a href="https://zh.wikipedia.org/wiki/面向对象程序设计" target="_blank" rel="noopener">面向对象</a>设计模式常以<strong>类</strong>或<strong>对象</strong>来描述其中的关系和相互作用，但不涉用来完成应用程序的特定类别或对象。设计模式能使不稳定依赖于相对稳定、具体依赖于相对抽象，避免会引起麻烦的紧耦合，以增强软件设计面对并适应变化的能力。 学习设计模式，关键是学习设计思想，不为设计而设计，需合理平衡设计模式的复杂度和灵活性。 <strong>须知设计模式并不是万能的！！！</strong></p>
                  </blockquote>
                  <h2 id="设计模式符合什么原则？"><a href="#设计模式符合什么原则？" class="headerlink" title="设计模式符合什么原则？"></a>设计模式符合什么原则？</h2>
                  <h3 id="开闭原则-Open-Colse-Principle-："><a href="#开闭原则-Open-Colse-Principle-：" class="headerlink" title="开闭原则(Open Colse Principle)："></a>开闭原则(Open Colse Principle)：</h3>
                  <p>软件对拓展开发，对修改关闭。</p>
                  <blockquote>
                    <p>理解：在增加新功能的时候，能不改代码就尽量不要改，如果只增加部分代码便可完成新功能，即是最好。</p>
                  </blockquote>
                  <h3 id="里氏替换原则-Liskov-Substitution-Principle-："><a href="#里氏替换原则-Liskov-Substitution-Principle-：" class="headerlink" title="里氏替换原则(Liskov Substitution Principle)："></a>里氏替换原则(Liskov Substitution Principle)：</h3>
                  <p>面向对象设计原则(六大原则)</p>
                  <blockquote>
                    <p>理解：若调用父类方法可成功，即调用成调用其子类亦可成功</p>
                  </blockquote>
                  <h2 id="面向对象六大设计原则："><a href="#面向对象六大设计原则：" class="headerlink" title="面向对象六大设计原则："></a>面向对象六大设计原则：</h2>
                  <p><strong>英文名称</strong></p>
                  <p><strong>缩写</strong></p>
                  <p><strong>中文名称</strong></p>
                  <p>Single Responsibility Principle</p>
                  <p>SRP</p>
                  <p>单一职责原则</p>
                  <p>Open Close Principle</p>
                  <p>OCP</p>
                  <p>开闭原则</p>
                  <p>Liskov Substitution Principle</p>
                  <p>LSP</p>
                  <p>里氏替换原则</p>
                  <p>Law of Demeter （ Least Knowledge Principle）</p>
                  <p>LoD</p>
                  <p>迪米特法则（最少知道原则）</p>
                  <p>Interface Segregation Principle</p>
                  <p>ISP</p>
                  <p>接口分离原则</p>
                  <p>Dependency Inversion Principle</p>
                  <p>DIP</p>
                  <p>依赖倒置原则</p>
                  <h2 id="常用设计模式概况："><a href="#常用设计模式概况：" class="headerlink" title="常用设计模式概况："></a>常用设计模式概况：</h2>
                  <p>[gallery columns=”1” size=”full” ids=”9642”]</p>
                  <h3 id="创建型模式（Creational-Patterns）："><a href="#创建型模式（Creational-Patterns）：" class="headerlink" title="创建型模式（Creational Patterns）："></a>创建型模式（<strong>Creational Patterns</strong>）：</h3>
                  <p>如何创建对象? 核心思想是要把对象的创建和使用分离，从而使得二者可以相对独立地变换。这些模式更加关注对象之间的创建</p>
                  <ul>
                    <li><strong>单例模式：Singleton Pattern</strong></li>
                    <li><strong>多例模式：Multiton Pattern</strong></li>
                    <li><strong>工厂模式：Factory Pattern</strong></li>
                    <li><strong>静态工厂模式：Static Factory Pattern</strong></li>
                    <li><strong>抽象工厂模式：Abstract Factory Pattern</strong></li>
                    <li><strong>原型模式：Prototype Pattern</strong></li>
                    <li><strong>建造者模式：Builder Pattern</strong></li>
                    <li><strong>对象池模式：Pool Pattern</strong></li>
                  </ul>
                  <h3 id="结构型模式-Structural-Patterns-："><a href="#结构型模式-Structural-Patterns-：" class="headerlink" title="结构型模式(Structural Patterns)："></a>结构型模式(<strong>Structural Patterns</strong>)：</h3>
                  <p>如何组合各种对象，以便于更好、更灵活的结构？面向对象的继承机制虽提供了基本的子类继承与拓展父类的功能，但结构型模式却不仅是简单的继承，还有更多的通过组合，使之与运行期的动态组合实现更加灵活的功能。这些模式更加关注对象之间的组合</p>
                  <ul>
                    <li><strong>组合模式(Composite)</strong></li>
                    <li><strong>桥接模式(Bridge)</strong></li>
                    <li><strong>适配器模式(Adapter)</strong></li>
                    <li><strong>过滤器模式（Filter、Criteria Pattern</strong></li>
                    <li><strong>装饰模式(Decorator)</strong></li>
                    <li><strong>外观模式(Facade)</strong></li>
                    <li><strong>门面模式：Facade</strong></li>
                    <li><strong>享元模式(Flyweight)</strong></li>
                    <li><strong>代理模式(Proxy)</strong></li>
                    <li><strong>数据映射模式：Data Mapper</strong></li>
                    <li><strong>依赖注入模式：Dependency Injection</strong></li>
                    <li><strong>流接口模式：Fluent Interface</strong></li>
                    <li><strong>注册模式：Registry</strong></li>
                  </ul>
                  <h3 id="行为模式（Behavioral-Patterns）："><a href="#行为模式（Behavioral-Patterns）：" class="headerlink" title="行为模式（Behavioral Patterns）："></a>行为模式（Behavioral Patterns）：</h3>
                  <p>行为模式主要涉及对象与函数（算法）之间的职责分配，通过对象及函数灵活组合。此种模式更加关注对象之间的通信 <strong>责任链模式：Chain of Responsibility Pattern</strong> <strong>命令模式：Command Pattern</strong> <strong>解释器模式：Interpreter Pattern</strong> <strong>迭代器模式：（Iterator Pattern</strong> <strong>中介者模式：Mediator Pattern</strong> <strong>备忘录模式：Memento Pattern</strong> <strong>观察者模式：Observer Pattern</strong> <strong>状态模式：State Pattern</strong> <strong>空对象模式：Null Object Pattern</strong> <strong>策略模式：Strategy Pattern</strong> <strong>模板模式：Template Pattern</strong> <strong>访问者模式：Visitor Pattern</strong> <strong>规格模式：Specification</strong> <img src="https://qiniu.cuiqingcai.com/wp-content/uploads/2020/08/设计者之间的关系-1.jpg" alt=""></p>
                  <blockquote>
                    <p>有不少的人说程序= 算法+ 数据结构，但个人认为程序 = 架构 + 设计模式 + 数据结构与算法 接下来将一起对本文中面向对象原则及设计模式进行详细的学习，同时我也会不断更新算法与数据结构相关的知识，让我们一起学习起来</p>
                  </blockquote>
                  </p>
                </div>
              </div>
              <div class="post-meta">
                <span class="post-meta-item">
                  <span class="post-meta-item-icon">
                    <i class="far fa-user"></i>
                  </span>
                  <span class="post-meta-item-text">作者</span>
                  <span><a href="/authors/Payne" class="author" itemprop="url" rel="index">Payne</a></span>
                </span>
                <span class="post-meta-item">
                  <span class="post-meta-item-icon">
                    <i class="far fa-calendar"></i>
                  </span>
                  <span class="post-meta-item-text">发表于</span>
                  <time title="创建时间：2020-08-29 23:59:23" itemprop="dateCreated datePublished" datetime="2020-08-29T23:59:23+08:00">2020-08-29</time>
                </span>
                <span id="/9640.html" class="post-meta-item leancloud_visitors" data-flag-title="浅淡程序设计模式-总纲篇" title="阅读次数">
                  <span class="post-meta-item-icon">
                    <i class="fa fa-eye"></i>
                  </span>
                  <span class="post-meta-item-text">阅读次数：</span>
                  <span class="leancloud-visitors-count"></span>
                </span>
                <span class="post-meta-item" title="本文字数">
                  <span class="post-meta-item-icon">
                    <i class="far fa-file-word"></i>
                  </span>
                  <span class="post-meta-item-text">本文字数：</span>
                  <span>2.2k</span>
                </span>
                <span class="post-meta-item" title="阅读时长">
                  <span class="post-meta-item-icon">
                    <i class="far fa-clock"></i>
                  </span>
                  <span class="post-meta-item-text">阅读时长 &asymp;</span>
                  <span>2 分钟</span>
                </span>
              </div>
            </article>
            <script>
              document.querySelectorAll('.random').forEach(item => item.src = "https://picsum.photos/id/" + Math.floor(Math.random() * Math.floor(300)) + "/200/133")

            </script>
            <nav class="pagination">
              <a class="extend prev" rel="prev" href="/page/5/"><i class="fa fa-angle-left" aria-label="上一页"></i></a><a class="page-number" href="/">1</a><span class="space">&hellip;</span><a class="page-number" href="/page/5/">5</a><span class="page-number current">6</span><a class="page-number" href="/page/7/">7</a><span class="space">&hellip;</span><a class="page-number" href="/page/31/">31</a><a class="extend next" rel="next" href="/page/7/"><i class="fa fa-angle-right" aria-label="下一页"></i></a>
            </nav>
          </div>
          <script>
            window.addEventListener('tabs:register', () =>
            {
              let
              {
                activeClass
              } = CONFIG.comments;
              if (CONFIG.comments.storage)
              {
                activeClass = localStorage.getItem('comments_active') || activeClass;
              }
              if (activeClass)
              {
                let activeTab = document.querySelector(`a[href="#comment-${activeClass}"]`);
                if (activeTab)
                {
                  activeTab.click();
                }
              }
            });
            if (CONFIG.comments.storage)
            {
              window.addEventListener('tabs:click', event =>
              {
                if (!event.target.matches('.tabs-comment .tab-content .tab-pane')) return;
                let commentClass = event.target.classList[1];
                localStorage.setItem('comments_active', commentClass);
              });
            }

          </script>
        </div>
        <div class="toggle sidebar-toggle">
          <span class="toggle-line toggle-line-first"></span>
          <span class="toggle-line toggle-line-middle"></span>
          <span class="toggle-line toggle-line-last"></span>
        </div>
        <aside class="sidebar">
          <div class="sidebar-inner">
            <ul class="sidebar-nav motion-element">
              <li class="sidebar-nav-toc"> 文章目录 </li>
              <li class="sidebar-nav-overview"> 站点概览 </li>
            </ul>
            <!--noindex-->
            <div class="post-toc-wrap sidebar-panel">
            </div>
            <!--/noindex-->
            <div class="site-overview-wrap sidebar-panel">
              <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
                <img class="site-author-image" itemprop="image" alt="崔庆才" src="/images/avatar.png">
                <p class="site-author-name" itemprop="name">崔庆才</p>
                <div class="site-description" itemprop="description">崔庆才的个人站点，记录生活的瞬间，分享学习的心得。</div>
              </div>
              <div class="site-state-wrap motion-element">
                <nav class="site-state">
                  <div class="site-state-item site-state-posts">
                    <a href="/archives/">
                      <span class="site-state-item-count">608</span>
                      <span class="site-state-item-name">日志</span>
                    </a>
                  </div>
                  <div class="site-state-item site-state-categories">
                    <a href="/categories/">
                      <span class="site-state-item-count">24</span>
                      <span class="site-state-item-name">分类</span></a>
                  </div>
                  <div class="site-state-item site-state-tags">
                    <a href="/tags/">
                      <span class="site-state-item-count">156</span>
                      <span class="site-state-item-name">标签</span></a>
                  </div>
                </nav>
              </div>
              <div class="links-of-author motion-element">
                <span class="links-of-author-item">
                  <a href="https://github.com/Germey" title="GitHub → https:&#x2F;&#x2F;github.com&#x2F;Germey" rel="noopener" target="_blank"><i class="fab fa-github fa-fw"></i>GitHub</a>
                </span>
                <span class="links-of-author-item">
                  <a href="mailto:cqc@cuiqingcai.com.com" title="邮件 → mailto:cqc@cuiqingcai.com.com" rel="noopener" target="_blank"><i class="fa fa-envelope fa-fw"></i>邮件</a>
                </span>
                <span class="links-of-author-item">
                  <a href="https://weibo.com/cuiqingcai" title="微博 → https:&#x2F;&#x2F;weibo.com&#x2F;cuiqingcai" rel="noopener" target="_blank"><i class="fab fa-weibo fa-fw"></i>微博</a>
                </span>
                <span class="links-of-author-item">
                  <a href="https://www.zhihu.com/people/Germey" title="知乎 → https:&#x2F;&#x2F;www.zhihu.com&#x2F;people&#x2F;Germey" rel="noopener" target="_blank"><i class="fa fa-magic fa-fw"></i>知乎</a>
                </span>
              </div>
            </div>
            <div style=" width: 100%;" class="sidebar-panel sidebar-panel-image sidebar-panel-active">
              <a href="https://tutorial.lengyue.video/?coupon=12ef4b1a-a3db-11ea-bb37-0242ac130002_cqx_850" target="_blank" rel="noopener">
                <img src="https://qiniu.cuiqingcai.com/bco2a.png" style=" width: 100%;">
              </a>
            </div>
            <div style=" width: 100%;" class="sidebar-panel sidebar-panel-image sidebar-panel-active">
              <a href="http://www.ipidea.net/?utm-source=cqc&utm-keyword=?cqc" target="_blank" rel="noopener">
                <img src="https://qiniu.cuiqingcai.com/0ywun.png" style=" width: 100%;">
              </a>
            </div>
            <div class="sidebar-panel sidebar-panel-tags sidebar-panel-active">
              <h4 class="name"> 标签云 </h4>
              <div class="content">
                <a href="/tags/2048/" style="font-size: 10px;">2048</a> <a href="/tags/API/" style="font-size: 10px;">API</a> <a href="/tags/Bootstrap/" style="font-size: 11.25px;">Bootstrap</a> <a href="/tags/CDN/" style="font-size: 10px;">CDN</a> <a href="/tags/CQC/" style="font-size: 10px;">CQC</a> <a href="/tags/CSS/" style="font-size: 10px;">CSS</a> <a href="/tags/CSS-%E5%8F%8D%E7%88%AC%E8%99%AB/" style="font-size: 10px;">CSS 反爬虫</a> <a href="/tags/CV/" style="font-size: 10px;">CV</a> <a href="/tags/Django/" style="font-size: 10px;">Django</a> <a href="/tags/Eclipse/" style="font-size: 11.25px;">Eclipse</a> <a href="/tags/FTP/" style="font-size: 10px;">FTP</a> <a href="/tags/Git/" style="font-size: 10px;">Git</a> <a href="/tags/GitHub/" style="font-size: 13.75px;">GitHub</a> <a href="/tags/HTML5/" style="font-size: 10px;">HTML5</a> <a href="/tags/Hexo/" style="font-size: 10px;">Hexo</a> <a href="/tags/IT/" style="font-size: 10px;">IT</a> <a href="/tags/JSP/" style="font-size: 10px;">JSP</a> <a href="/tags/JavaScript/" style="font-size: 10px;">JavaScript</a> <a href="/tags/K8s/" style="font-size: 10px;">K8s</a> <a href="/tags/LOGO/" style="font-size: 10px;">LOGO</a> <a href="/tags/Linux/" style="font-size: 10px;">Linux</a> <a href="/tags/MIUI/" style="font-size: 10px;">MIUI</a> <a href="/tags/MongoDB/" style="font-size: 10px;">MongoDB</a> <a href="/tags/Mysql/" style="font-size: 10px;">Mysql</a> <a href="/tags/NBA/" style="font-size: 10px;">NBA</a> <a href="/tags/PHP/" style="font-size: 11.25px;">PHP</a> <a href="/tags/PS/" style="font-size: 10px;">PS</a> <a href="/tags/Pathlib/" style="font-size: 10px;">Pathlib</a> <a href="/tags/PhantomJS/" style="font-size: 10px;">PhantomJS</a> <a href="/tags/Python/" style="font-size: 15px;">Python</a> <a href="/tags/Python3/" style="font-size: 12.5px;">Python3</a> <a href="/tags/Pythonic/" style="font-size: 10px;">Pythonic</a> <a href="/tags/QQ/" style="font-size: 10px;">QQ</a> <a href="/tags/Redis/" style="font-size: 10px;">Redis</a> <a href="/tags/SAE/" style="font-size: 10px;">SAE</a> <a href="/tags/SSH/" style="font-size: 10px;">SSH</a> <a href="/tags/SVG/" style="font-size: 10px;">SVG</a> <a href="/tags/Scrapy/" style="font-size: 10px;">Scrapy</a> <a href="/tags/Scrapy-redis/" style="font-size: 10px;">Scrapy-redis</a> <a href="/tags/Scrapy%E5%88%86%E5%B8%83%E5%BC%8F/" style="font-size: 10px;">Scrapy分布式</a> <a href="/tags/Selenium/" style="font-size: 10px;">Selenium</a> <a href="/tags/TKE/" style="font-size: 10px;">TKE</a> <a href="/tags/Ubuntu/" style="font-size: 11.25px;">Ubuntu</a> <a href="/tags/VS-Code/" style="font-size: 10px;">VS Code</a> <a href="/tags/Vs-Code/" style="font-size: 10px;">Vs Code</a> <a href="/tags/Vue/" style="font-size: 11.25px;">Vue</a> <a href="/tags/Webpack/" style="font-size: 10px;">Webpack</a> <a href="/tags/Windows/" style="font-size: 10px;">Windows</a> <a href="/tags/Winpcap/" style="font-size: 10px;">Winpcap</a> <a href="/tags/WordPress/" style="font-size: 13.75px;">WordPress</a> <a href="/tags/Youtube/" style="font-size: 11.25px;">Youtube</a> <a href="/tags/android/" style="font-size: 10px;">android</a> <a href="/tags/ansible/" style="font-size: 10px;">ansible</a> <a href="/tags/cocos2d-x/" style="font-size: 10px;">cocos2d-x</a> <a href="/tags/e6/" style="font-size: 10px;">e6</a> <a href="/tags/fitvids/" style="font-size: 10px;">fitvids</a> <a href="/tags/git/" style="font-size: 11.25px;">git</a> <a href="/tags/json/" style="font-size: 10px;">json</a> <a href="/tags/js%E9%80%86%E5%90%91/" style="font-size: 10px;">js逆向</a> <a href="/tags/kubernetes/" style="font-size: 10px;">kubernetes</a> <a href="/tags/log/" style="font-size: 10px;">log</a> <a href="/tags/logging/" style="font-size: 10px;">logging</a> <a href="/tags/matlab/" style="font-size: 11.25px;">matlab</a> <a href="/tags/python/" style="font-size: 20px;">python</a> <a href="/tags/pytube/" style="font-size: 11.25px;">pytube</a> <a href="/tags/pywin32/" style="font-size: 10px;">pywin32</a> <a href="/tags/style/" style="font-size: 10px;">style</a> <a href="/tags/tomcat/" style="font-size: 10px;">tomcat</a> <a href="/tags/ubuntu/" style="font-size: 10px;">ubuntu</a> <a href="/tags/uwsgi/" style="font-size: 10px;">uwsgi</a> <a href="/tags/vsftpd/" style="font-size: 10px;">vsftpd</a> <a href="/tags/wamp/" style="font-size: 10px;">wamp</a> <a href="/tags/wineQQ/" style="font-size: 10px;">wineQQ</a> <a href="/tags/%E4%B8%83%E7%89%9B/" style="font-size: 11.25px;">七牛</a> <a href="/tags/%E4%B8%8A%E6%B5%B7/" style="font-size: 10px;">上海</a> <a href="/tags/%E4%B8%AA%E4%BA%BA%E7%BD%91%E7%AB%99/" style="font-size: 10px;">个人网站</a> <a href="/tags/%E4%B8%BB%E9%A2%98/" style="font-size: 10px;">主题</a> <a href="/tags/%E4%BA%91%E4%BA%A7%E5%93%81/" style="font-size: 10px;">云产品</a> <a href="/tags/%E4%BA%91%E5%AD%98%E5%82%A8/" style="font-size: 10px;">云存储</a> <a href="/tags/%E4%BA%AC%E4%B8%9C%E4%BA%91/" style="font-size: 10px;">京东云</a> <a href="/tags/%E4%BA%BA%E5%B7%A5%E6%99%BA%E8%83%BD/" style="font-size: 12.5px;">人工智能</a> <a href="/tags/%E4%BB%A3%E7%90%86/" style="font-size: 10px;">代理</a> <a href="/tags/%E4%BB%A3%E7%A0%81/" style="font-size: 10px;">代码</a> <a href="/tags/%E4%BB%A3%E7%A0%81%E5%88%86%E4%BA%AB%E5%9B%BE/" style="font-size: 10px;">代码分享图</a> <a href="/tags/%E4%BC%98%E5%8C%96/" style="font-size: 10px;">优化</a> <a href="/tags/%E4%BD%8D%E8%BF%90%E7%AE%97/" style="font-size: 10px;">位运算</a> <a href="/tags/%E5%85%AC%E4%BC%97%E5%8F%B7/" style="font-size: 10px;">公众号</a> <a href="/tags/%E5%88%86%E4%BA%AB/" style="font-size: 10px;">分享</a> <a href="/tags/%E5%88%86%E5%B8%83%E5%BC%8F/" style="font-size: 10px;">分布式</a> <a href="/tags/%E5%88%9B%E4%B8%9A/" style="font-size: 10px;">创业</a> <a href="/tags/%E5%89%8D%E7%AB%AF/" style="font-size: 12.5px;">前端</a> <a href="/tags/%E5%8D%9A%E5%AE%A2/" style="font-size: 10px;">博客</a> <a href="/tags/%E5%8E%9F%E7%94%9FAPP/" style="font-size: 10px;">原生APP</a> <a href="/tags/%E5%8F%8D%E7%88%AC%E8%99%AB/" style="font-size: 12.5px;">反爬虫</a> <a href="/tags/%E5%91%BD%E4%BB%A4/" style="font-size: 10px;">命令</a> <a href="/tags/%E5%93%8D%E5%BA%94%E5%BC%8F%E5%B8%83%E5%B1%80/" style="font-size: 10px;">响应式布局</a> <a href="/tags/%E5%9E%83%E5%9C%BE%E9%82%AE%E4%BB%B6/" style="font-size: 10px;">垃圾邮件</a> <a href="/tags/%E5%9F%9F%E5%90%8D%E7%BB%91%E5%AE%9A/" style="font-size: 10px;">域名绑定</a> <a href="/tags/%E5%A4%8D%E7%9B%98/" style="font-size: 10px;">复盘</a> <a href="/tags/%E5%A4%A7%E4%BC%97%E7%82%B9%E8%AF%84/" style="font-size: 10px;">大众点评</a> <a href="/tags/%E5%AD%97%E4%BD%93%E5%8F%8D%E7%88%AC%E8%99%AB/" style="font-size: 10px;">字体反爬虫</a> <a href="/tags/%E5%AD%97%E7%AC%A6%E9%97%AE%E9%A2%98/" style="font-size: 10px;">字符问题</a> <a href="/tags/%E5%AD%A6%E4%B9%A0%E6%96%B9%E6%B3%95/" style="font-size: 10px;">学习方法</a> <a href="/tags/%E5%AE%89%E5%8D%93/" style="font-size: 10px;">安卓</a> <a href="/tags/%E5%AE%9E%E7%94%A8/" style="font-size: 10px;">实用</a> <a href="/tags/%E5%B0%81%E9%9D%A2/" style="font-size: 10px;">封面</a> <a href="/tags/%E5%B4%94%E5%BA%86%E6%89%8D/" style="font-size: 18.75px;">崔庆才</a> <a href="/tags/%E5%B7%A5%E5%85%B7/" style="font-size: 12.5px;">工具</a> <a href="/tags/%E5%BC%80%E5%8F%91%E5%B7%A5%E5%85%B7/" style="font-size: 10px;">开发工具</a> <a href="/tags/%E5%BE%AE%E8%BD%AF/" style="font-size: 10px;">微软</a> <a href="/tags/%E6%80%9D%E8%80%83/" style="font-size: 10px;">思考</a> <a href="/tags/%E6%89%8B%E6%9C%BA%E8%AE%BF%E9%97%AE/" style="font-size: 10px;">手机访问</a> <a href="/tags/%E6%95%99%E7%A8%8B/" style="font-size: 10px;">教程</a> <a href="/tags/%E6%95%99%E8%82%B2/" style="font-size: 10px;">教育</a> <a href="/tags/%E6%96%B0%E4%B9%A6/" style="font-size: 12.5px;">新书</a> <a href="/tags/%E6%96%B9%E6%B3%95%E8%AE%BA/" style="font-size: 10px;">方法论</a> <a href="/tags/%E6%97%85%E6%B8%B8/" style="font-size: 10px;">旅游</a> <a href="/tags/%E6%97%A5%E5%BF%97/" style="font-size: 10px;">日志</a> <a href="/tags/%E6%9A%97%E6%97%B6%E9%97%B4/" style="font-size: 10px;">暗时间</a> <a href="/tags/%E6%9D%9C%E5%85%B0%E7%89%B9/" style="font-size: 11.25px;">杜兰特</a> <a href="/tags/%E6%A1%8C%E9%9D%A2/" style="font-size: 10px;">桌面</a> <a href="/tags/%E6%AD%8C%E5%8D%95/" style="font-size: 10px;">歌单</a> <a href="/tags/%E6%B1%9F%E5%8D%97/" style="font-size: 10px;">江南</a> <a href="/tags/%E6%B8%B8%E6%88%8F/" style="font-size: 10px;">游戏</a> <a href="/tags/%E7%84%A6%E8%99%91/" style="font-size: 10px;">焦虑</a> <a href="/tags/%E7%88%AC%E8%99%AB/" style="font-size: 16.25px;">爬虫</a> <a href="/tags/%E7%88%AC%E8%99%AB%E4%B9%A6%E7%B1%8D/" style="font-size: 11.25px;">爬虫书籍</a> <a href="/tags/%E7%8E%AF%E5%A2%83%E5%8F%98%E9%87%8F/" style="font-size: 10px;">环境变量</a> <a href="/tags/%E7%94%9F%E6%B4%BB%E7%AC%94%E8%AE%B0/" style="font-size: 10px;">生活笔记</a> <a href="/tags/%E7%99%BB%E5%BD%95/" style="font-size: 10px;">登录</a> <a href="/tags/%E7%9F%A5%E4%B9%8E/" style="font-size: 10px;">知乎</a> <a href="/tags/%E7%9F%AD%E4%BF%A1/" style="font-size: 10px;">短信</a> <a href="/tags/%E7%9F%AD%E4%BF%A1%E9%AA%8C%E8%AF%81%E7%A0%81/" style="font-size: 10px;">短信验证码</a> <a href="/tags/%E7%AC%94%E8%AE%B0%E8%BD%AF%E4%BB%B6/" style="font-size: 10px;">笔记软件</a> <a href="/tags/%E7%AF%AE%E7%BD%91/" style="font-size: 10px;">篮网</a> <a href="/tags/%E7%BA%B8%E5%BC%A0/" style="font-size: 10px;">纸张</a> <a href="/tags/%E7%BB%84%E4%BB%B6/" style="font-size: 10px;">组件</a> <a href="/tags/%E7%BD%91%E7%AB%99/" style="font-size: 10px;">网站</a> <a href="/tags/%E7%BD%91%E7%BB%9C%E7%88%AC%E8%99%AB/" style="font-size: 11.25px;">网络爬虫</a> <a href="/tags/%E7%BE%8E%E5%AD%A6/" style="font-size: 10px;">美学</a> <a href="/tags/%E8%82%89%E5%A4%B9%E9%A6%8D/" style="font-size: 10px;">肉夹馍</a> <a href="/tags/%E8%85%BE%E8%AE%AF%E4%BA%91/" style="font-size: 10px;">腾讯云</a> <a href="/tags/%E8%87%AA%E5%BE%8B/" style="font-size: 10px;">自律</a> <a href="/tags/%E8%A5%BF%E5%B0%91%E7%88%B7/" style="font-size: 10px;">西少爷</a> <a href="/tags/%E8%A7%86%E9%A2%91/" style="font-size: 10px;">视频</a> <a href="/tags/%E8%B0%B7%E6%AD%8C%E9%AA%8C%E8%AF%81%E7%A0%81/" style="font-size: 10px;">谷歌验证码</a> <a href="/tags/%E8%BF%90%E8%90%A5/" style="font-size: 10px;">运营</a> <a href="/tags/%E8%BF%9C%E7%A8%8B/" style="font-size: 10px;">远程</a> <a href="/tags/%E9%80%86%E5%90%91/" style="font-size: 10px;">逆向</a> <a href="/tags/%E9%85%8D%E7%BD%AE/" style="font-size: 10px;">配置</a> <a href="/tags/%E9%87%8D%E8%A3%85/" style="font-size: 10px;">重装</a> <a href="/tags/%E9%98%BF%E6%9D%9C/" style="font-size: 10px;">阿杜</a> <a href="/tags/%E9%9D%99%E8%A7%85/" style="font-size: 17.5px;">静觅</a> <a href="/tags/%E9%A2%A0%E8%A6%86/" style="font-size: 10px;">颠覆</a> <a href="/tags/%E9%A3%9E%E4%BF%A1/" style="font-size: 10px;">飞信</a> <a href="/tags/%E9%B8%BF%E8%92%99/" style="font-size: 10px;">鸿蒙</a>
              </div>
              <script>
                const tagsColors = ['#00a67c', '#5cb85c', '#d9534f', '#567e95', '#b37333', '#f4843d', '#15a287']
                const tagsElements = document.querySelectorAll('.sidebar-panel-tags .content a')
                tagsElements.forEach((item) =>
                {
                  item.style.backgroundColor = tagsColors[Math.floor(Math.random() * tagsColors.length)]
                })

              </script>
            </div>
            <div class="sidebar-panel sidebar-panel-categories sidebar-panel-active">
              <h4 class="name"> 分类 </h4>
              <div class="content">
                <ul class="category-list">
                  <li class="category-list-item"><a class="category-list-link" href="/categories/C-C/">C/C++</a><span class="category-list-count">23</span></li>
                  <li class="category-list-item"><a class="category-list-link" href="/categories/HTML/">HTML</a><span class="category-list-count">14</span></li>
                  <li class="category-list-item"><a class="category-list-link" href="/categories/Java/">Java</a><span class="category-list-count">5</span></li>
                  <li class="category-list-item"><a class="category-list-link" href="/categories/JavaScript/">JavaScript</a><span class="category-list-count">26</span></li>
                  <li class="category-list-item"><a class="category-list-link" href="/categories/Linux/">Linux</a><span class="category-list-count">15</span></li>
                  <li class="category-list-item"><a class="category-list-link" href="/categories/Markdown/">Markdown</a><span class="category-list-count">1</span></li>
                  <li class="category-list-item"><a class="category-list-link" href="/categories/Net/">Net</a><span class="category-list-count">4</span></li>
                  <li class="category-list-item"><a class="category-list-link" href="/categories/Other/">Other</a><span class="category-list-count">39</span></li>
                  <li class="category-list-item"><a class="category-list-link" href="/categories/PHP/">PHP</a><span class="category-list-count">27</span></li>
                  <li class="category-list-item"><a class="category-list-link" href="/categories/Paper/">Paper</a><span class="category-list-count">2</span></li>
                  <li class="category-list-item"><a class="category-list-link" href="/categories/Python/">Python</a><span class="category-list-count">261</span></li>
                  <li class="category-list-item"><a class="category-list-link" href="/categories/TypeScript/">TypeScript</a><span class="category-list-count">2</span></li>
                  <li class="category-list-item"><a class="category-list-link" href="/categories/%E4%B8%AA%E4%BA%BA%E5%B1%95%E7%A4%BA/">个人展示</a><span class="category-list-count">1</span></li>
                  <li class="category-list-item"><a class="category-list-link" href="/categories/%E4%B8%AA%E4%BA%BA%E6%97%A5%E8%AE%B0/">个人日记</a><span class="category-list-count">9</span></li>
                  <li class="category-list-item"><a class="category-list-link" href="/categories/%E4%B8%AA%E4%BA%BA%E8%AE%B0%E5%BD%95/">个人记录</a><span class="category-list-count">4</span></li>
                  <li class="category-list-item"><a class="category-list-link" href="/categories/%E4%B8%AA%E4%BA%BA%E9%9A%8F%E7%AC%94/">个人随笔</a><span class="category-list-count">15</span></li>
                  <li class="category-list-item"><a class="category-list-link" href="/categories/%E5%AE%89%E8%A3%85%E9%85%8D%E7%BD%AE/">安装配置</a><span class="category-list-count">59</span></li>
                  <li class="category-list-item"><a class="category-list-link" href="/categories/%E6%8A%80%E6%9C%AF%E6%9D%82%E8%B0%88/">技术杂谈</a><span class="category-list-count">88</span></li>
                  <li class="category-list-item"><a class="category-list-link" href="/categories/%E6%9C%AA%E5%88%86%E7%B1%BB/">未分类</a><span class="category-list-count">1</span></li>
                  <li class="category-list-item"><a class="category-list-link" href="/categories/%E7%94%9F%E6%B4%BB%E7%AC%94%E8%AE%B0/">生活笔记</a><span class="category-list-count">1</span></li>
                  <li class="category-list-item"><a class="category-list-link" href="/categories/%E7%A6%8F%E5%88%A9%E4%B8%93%E5%8C%BA/">福利专区</a><span class="category-list-count">6</span></li>
                  <li class="category-list-item"><a class="category-list-link" href="/categories/%E8%81%8C%E4%BD%8D%E6%8E%A8%E8%8D%90/">职位推荐</a><span class="category-list-count">2</span></li>
                </ul>
              </div>
            </div>
            <div class="sidebar-panel sidebar-panel-friends sidebar-panel-active">
              <h4 class="name"> 友情链接 </h4>
              <ul class="friends">
                <li class="friend">
                  <span class="logo">
                    <img src="https://qiniu.cuiqingcai.com/j2dub.jpg">
                  </span>
                  <span class="link">
                    <a href="https://www.findhao.net/" target="_blank" rel="noopener">FindHao</a>
                  </span>
                </li>
                <li class="friend">
                  <span class="logo">
                    <img src="https://qiniu.cuiqingcai.com/ou6mm.jpg">
                  </span>
                  <span class="link">
                    <a href="https://diygod.me/" target="_blank" rel="noopener">DIYgod</a>
                  </span>
                </li>
                <li class="friend">
                  <span class="logo">
                    <img src="https://qiniu.cuiqingcai.com/6apxu.jpg">
                  </span>
                  <span class="link">
                    <a href="https://www.51dev.com/" target="_blank" rel="noopener">IT技术社区</a>
                  </span>
                </li>
                <li class="friend">
                  <span class="logo">
                    <img src="https://www.jankl.com/img/titleshu.jpg">
                  </span>
                  <span class="link">
                    <a href="https://www.jankl.com/" target="_blank" rel="noopener">liberalist</a>
                  </span>
                </li>
                <li class="friend">
                  <span class="logo">
                    <img src="https://qiniu.cuiqingcai.com/bqlbs.png">
                  </span>
                  <span class="link">
                    <a href="http://www.urselect.com/" target="_blank" rel="noopener">优社电商</a>
                  </span>
                </li>
                <li class="friend">
                  <span class="logo">
                    <img src="https://qiniu.cuiqingcai.com/8s88c.jpg">
                  </span>
                  <span class="link">
                    <a href="https://www.yuanrenxue.com/" target="_blank" rel="noopener">猿人学</a>
                  </span>
                </li>
                <li class="friend">
                  <span class="logo">
                    <img src="https://qiniu.cuiqingcai.com/2wgg5.jpg">
                  </span>
                  <span class="link">
                    <a href="https://www.yunlifang.cn/" target="_blank" rel="noopener">云立方</a>
                  </span>
                </li>
                <li class="friend">
                  <span class="logo">
                    <img src="https://qiniu.cuiqingcai.com/shwr6.png">
                  </span>
                  <span class="link">
                    <a href="http://lanbing510.info/" target="_blank" rel="noopener">冰蓝</a>
                  </span>
                </li>
                <li class="friend">
                  <span class="logo">
                    <img src="https://qiniu.cuiqingcai.com/blvoh.jpg">
                  </span>
                  <span class="link">
                    <a href="https://lengyue.me/" target="_blank" rel="noopener">冷月</a>
                  </span>
                </li>
                <li class="friend">
                  <span class="logo">
                    <img src="http://qianxunclub.com/favicon.png">
                  </span>
                  <span class="link">
                    <a href="http://qianxunclub.com/" target="_blank" rel="noopener">千寻啊千寻</a>
                  </span>
                </li>
                <li class="friend">
                  <span class="logo">
                    <img src="https://qiniu.cuiqingcai.com/0044u.jpg">
                  </span>
                  <span class="link">
                    <a href="http://kodcloud.com/" target="_blank" rel="noopener">可道云</a>
                  </span>
                </li>
                <li class="friend">
                  <span class="logo">
                    <img src="https://qiniu.cuiqingcai.com/ygnpn.jpg">
                  </span>
                  <span class="link">
                    <a href="http://www.kunkundashen.cn/" target="_blank" rel="noopener">坤坤大神</a>
                  </span>
                </li>
                <li class="friend">
                  <span class="logo">
                    <img src="https://qiniu.cuiqingcai.com/22uv1.png">
                  </span>
                  <span class="link">
                    <a href="http://www.cenchong.com/" target="_blank" rel="noopener">岑冲博客</a>
                  </span>
                </li>
                <li class="friend">
                  <span class="logo">
                    <img src="https://qiniu.cuiqingcai.com/ev9kl.png">
                  </span>
                  <span class="link">
                    <a href="http://www.zxiaoji.com/" target="_blank" rel="noopener">张小鸡</a>
                  </span>
                </li>
                <li class="friend">
                  <span class="logo">
                    <img src="https://www.503error.com/favicon.ico">
                  </span>
                  <span class="link">
                    <a href="https://www.503error.com/" target="_blank" rel="noopener">张志明个人博客</a>
                  </span>
                </li>
                <li class="friend">
                  <span class="logo">
                    <img src="https://qiniu.cuiqingcai.com/x714o.jpg">
                  </span>
                  <span class="link">
                    <a href="http://www.hubwiz.com/" target="_blank" rel="noopener">汇智网</a>
                  </span>
                </li>
                <li class="friend">
                  <span class="logo">
                    <img src="https://qiniu.cuiqingcai.com/129d8.png">
                  </span>
                  <span class="link">
                    <a href="https://www.bysocket.com/" target="_blank" rel="noopener">泥瓦匠BYSocket</a>
                  </span>
                </li>
                <li class="friend">
                  <span class="logo">
                    <img src="https://www.xiongge.club/favicon.ico">
                  </span>
                  <span class="link">
                    <a href="https://www.xiongge.club/" target="_blank" rel="noopener">熊哥club</a>
                  </span>
                </li>
                <li class="friend">
                  <span class="logo">
                    <img src="https://qiniu.cuiqingcai.com/3w4fe.png">
                  </span>
                  <span class="link">
                    <a href="https://zerlong.com/" target="_blank" rel="noopener">知语</a>
                  </span>
                </li>
                <li class="friend">
                  <span class="logo">
                    <img src="https://qiniu.cuiqingcai.com/44hxf.png">
                  </span>
                  <span class="link">
                    <a href="http://redstonewill.com/" target="_blank" rel="noopener">红色石头</a>
                  </span>
                </li>
                <li class="friend">
                  <span class="logo">
                    <img src="https://qiniu.cuiqingcai.com/8g1fk.jpg">
                  </span>
                  <span class="link">
                    <a href="http://www.laodong.me/" target="_blank" rel="noopener">老董博客</a>
                  </span>
                </li>
                <li class="friend">
                  <span class="logo">
                    <img src="https://qiniu.cuiqingcai.com/wkaus.jpg">
                  </span>
                  <span class="link">
                    <a href="https://zhaoshuai.me/" target="_blank" rel="noopener">碎念</a>
                  </span>
                </li>
                <li class="friend">
                  <span class="logo">
                    <img src="https://qiniu.cuiqingcai.com/pgo0r.jpg">
                  </span>
                  <span class="link">
                    <a href="https://www.chenwenguan.com/" target="_blank" rel="noopener">陈文管的博客</a>
                  </span>
                </li>
                <li class="friend">
                  <span class="logo">
                    <img src="https://qiniu.cuiqingcai.com/kk82a.jpg">
                  </span>
                  <span class="link">
                    <a href="https://www.lxlinux.net/" target="_blank" rel="noopener">良许Linux教程网</a>
                  </span>
                </li>
                <li class="friend">
                  <span class="logo">
                    <img src="https://qiniu.cuiqingcai.com/lj0t2.jpg">
                  </span>
                  <span class="link">
                    <a href="https://tanqingbo.cn/" target="_blank" rel="noopener">IT码农</a>
                  </span>
                </li>
                <li class="friend">
                  <span class="logo">
                    <img src="https://qiniu.cuiqingcai.com/i8cdr.png">
                  </span>
                  <span class="link">
                    <a href="https://junyiseo.com/" target="_blank" rel="noopener">均益个人博客</a>
                  </span>
                </li>
                <li class="friend">
                  <span class="logo">
                    <img src="https://qiniu.cuiqingcai.com/chwv2.png">
                  </span>
                  <span class="link">
                    <a href="https://brucedone.com/" target="_blank" rel="noopener">大鱼的鱼塘</a>
                  </span>
                </li>
                <li class="friend">
                  <span class="logo">
                    <img src="https://qiniu.cuiqingcai.com/2y43o.png">
                  </span>
                  <span class="link">
                    <a href="http://bbs.nightteam.cn/" target="_blank" rel="noopener">夜幕爬虫安全论坛</a>
                  </span>
                </li>
                <li class="friend">
                  <span class="logo">
                    <img src="https://qiniu.cuiqingcai.com/zvc3w.jpg">
                  </span>
                  <span class="link">
                    <a href="https://www.weishidong.com/" target="_blank" rel="noopener">韦世东的技术专栏</a>
                  </span>
                </li>
                <li class="friend">
                  <span class="logo">
                    <img src="https://qiniu.cuiqingcai.com/ebudy.jpg">
                  </span>
                  <span class="link">
                    <a href="https://chuanjiabing.com/" target="_blank" rel="noopener">穿甲兵技术社区</a>
                  </span>
                </li>
              </ul>
            </div>
          </div>
        </aside>
        <div id="sidebar-dimmer"></div>
      </div>
    </main>
    <footer class="footer">
      <div class="footer-inner">
        <div class="copyright"> &copy; <span itemprop="copyrightYear">2021</span>
          <span class="with-love">
            <i class="fa fa-heart"></i>
          </span>
          <span class="author" itemprop="copyrightHolder">崔庆才丨静觅</span>
          <span class="post-meta-divider">|</span>
          <span class="post-meta-item-icon">
            <i class="fa fa-chart-area"></i>
          </span>
          <span title="站点总字数">2.6m</span>
          <span class="post-meta-divider">|</span>
          <span class="post-meta-item-icon">
            <i class="fa fa-coffee"></i>
          </span>
          <span title="站点阅读时长">39:54</span>
        </div>
        <div class="powered-by">由 <a href="https://hexo.io/" class="theme-link" rel="noopener" target="_blank">Hexo</a> & <a href="https://pisces.theme-next.org/" class="theme-link" rel="noopener" target="_blank">NexT.Pisces</a> 强力驱动 </div>
        <div class="beian"><a href="https://beian.miit.gov.cn/" rel="noopener" target="_blank">京ICP备18015597号-1 </a>
        </div>
        <script>
          (function ()
          {
            function leancloudSelector(url)
            {
              url = encodeURI(url);
              return document.getElementById(url).querySelector('.leancloud-visitors-count');
            }

            function addCount(Counter)
            {
              var visitors = document.querySelector('.leancloud_visitors');
              var url = decodeURI(visitors.id);
              var title = visitors.dataset.flagTitle;
              Counter('get', '/classes/Counter?where=' + encodeURIComponent(JSON.stringify(
              {
                url
              }))).then(response => response.json()).then((
              {
                results
              }) =>
              {
                if (results.length > 0)
                {
                  var counter = results[0];
                  leancloudSelector(url).innerText = counter.time + 1;
                  Counter('put', '/classes/Counter/' + counter.objectId,
                  {
                    time:
                    {
                      '__op': 'Increment',
                      'amount': 1
                    }
                  }).catch(error =>
                  {
                    console.error('Failed to save visitor count', error);
                  });
                }
                else
                {
                  Counter('post', '/classes/Counter',
                  {
                    title,
                    url,
                    time: 1
                  }).then(response => response.json()).then(() =>
                  {
                    leancloudSelector(url).innerText = 1;
                  }).catch(error =>
                  {
                    console.error('Failed to create', error);
                  });
                }
              }).catch(error =>
              {
                console.error('LeanCloud Counter Error', error);
              });
            }

            function showTime(Counter)
            {
              var visitors = document.querySelectorAll('.leancloud_visitors');
              var entries = [...visitors].map(element =>
              {
                return decodeURI(element.id);
              });
              Counter('get', '/classes/Counter?where=' + encodeURIComponent(JSON.stringify(
              {
                url:
                {
                  '$in': entries
                }
              }))).then(response => response.json()).then((
              {
                results
              }) =>
              {
                for (let url of entries)
                {
                  let target = results.find(item => item.url === url);
                  leancloudSelector(url).innerText = target ? target.time : 0;
                }
              }).catch(error =>
              {
                console.error('LeanCloud Counter Error', error);
              });
            }
            let
            {
              app_id,
              app_key,
              server_url
            } = {
              "enable": true,
              "app_id": "6X5dRQ0pnPWJgYy8SXOg0uID-gzGzoHsz",
              "app_key": "ziLDVEy73ne5HtFTiGstzHMS",
              "server_url": "https://6x5drq0p.lc-cn-n1-shared.com",
              "security": false
            };

            function fetchData(api_server)
            {
              var Counter = (method, url, data) =>
              {
                return fetch(`${api_server}/1.1${url}`,
                {
                  method,
                  headers:
                  {
                    'X-LC-Id': app_id,
                    'X-LC-Key': app_key,
                    'Content-Type': 'application/json',
                  },
                  body: JSON.stringify(data)
                });
              };
              if (CONFIG.page.isPost)
              {
                if (CONFIG.hostname !== location.hostname) return;
                addCount(Counter);
              }
              else if (document.querySelectorAll('.post-title-link').length >= 1)
              {
                showTime(Counter);
              }
            }
            let api_server = app_id.slice(-9) !== '-MdYXbMMI' ? server_url : `https://${app_id.slice(0, 8).toLowerCase()}.api.lncldglobal.com`;
            if (api_server)
            {
              fetchData(api_server);
            }
            else
            {
              fetch('https://app-router.leancloud.cn/2/route?appId=' + app_id).then(response => response.json()).then((
              {
                api_server
              }) =>
              {
                fetchData('https://' + api_server);
              });
            }
          })();

        </script>
      </div>
      <div class="footer-stat">
        <span id="cnzz_stat_icon_1279355174"></span>
        <script type="text/javascript">
          document.write(unescape("%3Cspan id='cnzz_stat_icon_1279355174'%3E%3C/span%3E%3Cscript src='https://v1.cnzz.com/z_stat.php%3Fid%3D1279355174%26online%3D1%26show%3Dline' type='text/javascript'%3E%3C/script%3E"));

        </script>
      </div>
    </footer>
  </div>
  <script src="//cdn.jsdelivr.net/npm/animejs@3.2.1/lib/anime.min.js"></script>
  <script src="//cdn.jsdelivr.net/npm/pangu@4/dist/browser/pangu.min.js"></script>
  <script src="/js/utils.js"></script>
  <script src="/.js"></script>
  <script src="/js/schemes/pisces.js"></script>
  <script src="/.js"></script>
  <script src="/js/next-boot.js"></script>
  <script src="/.js"></script>
  <script>
    (function ()
    {
      var canonicalURL, curProtocol;
      //Get the <link> tag
      var x = document.getElementsByTagName("link");
      //Find the last canonical URL
      if (x.length > 0)
      {
        for (i = 0; i < x.length; i++)
        {
          if (x[i].rel.toLowerCase() == 'canonical' && x[i].href)
          {
            canonicalURL = x[i].href;
          }
        }
      }
      //Get protocol
      if (!canonicalURL)
      {
        curProtocol = window.location.protocol.split(':')[0];
      }
      else
      {
        curProtocol = canonicalURL.split(':')[0];
      }
      //Get current URL if the canonical URL does not exist
      if (!canonicalURL) canonicalURL = window.location.href;
      //Assign script content. Replace current URL with the canonical URL
      ! function ()
      {
        var e = /([http|https]:\/\/[a-zA-Z0-9\_\.]+\.baidu\.com)/gi,
          r = canonicalURL,
          t = document.referrer;
        if (!e.test(r))
        {
          var n = (String(curProtocol).toLowerCase() === 'https') ? "https://sp0.baidu.com/9_Q4simg2RQJ8t7jm9iCKT-xh_/s.gif" : "//api.share.baidu.com/s.gif";
          t ? (n += "?r=" + encodeURIComponent(document.referrer), r && (n += "&l=" + r)) : r && (n += "?l=" + r);
          var i = new Image;
          i.src = n
        }
      }(window);
    })();

  </script>
  <script src="/js/local-search.js"></script>
  <script src="/.js"></script>
</body>

</html>
